摘要:組成指針,指針代表捕獲異常的范圍,就是的范圍。當(dāng)觸發(fā)異常的字節(jié)碼的索引值在某個(gè)異常表?xiàng)l目的監(jiān)控范圍內(nèi),虛擬機(jī)會(huì)判斷所拋出的異常和該條目想要捕獲的異常是否匹配。
Java異常知識(shí) 1.異常的兩大關(guān)鍵因素
(1)拋出異常
1.顯式:應(yīng)用程序手動(dòng)拋出異常。具體就是使用throw拋出異常
2.隱式:Java虛擬機(jī)對(duì)于無法執(zhí)行的代碼,自動(dòng)拋出異常
(2)捕獲異常
1.try 代碼塊:用來標(biāo)記需要進(jìn)行異常監(jiān)控的代碼。
2.catch 代碼塊:跟在 try 代碼塊之后,用來捕獲在 try 代碼塊中觸發(fā)的某種指定類型的異常。除了聲明所捕獲異常的類型之外,catch 代碼塊還定義了針對(duì)該異常類型的異常處理器。在 Java中,try 代碼塊后面可以跟著多個(gè) catch 代碼塊,來捕獲不同類型的異常。Java 虛擬機(jī)會(huì)從上至下匹配異常處理器。因此,前面的 catch 代碼塊所捕獲的異常類型不能覆蓋后邊的,否則編譯器會(huì)報(bào)錯(cuò)。
3.fnally 代碼塊:跟在 try 代碼塊和 catch 代碼塊之后,用來聲明一段必定運(yùn)行的代碼。它的設(shè)計(jì)初衷是為了避免跳過某些關(guān)鍵的清理代碼,例如關(guān)閉已打開的系統(tǒng)資源。在程序正常執(zhí)行的情況下,這段代碼會(huì)在 try 代碼塊之后運(yùn)行。否則,也就是 try 代碼塊觸發(fā)異常的情況下,如果該異常沒有被捕獲,fnally 代碼塊會(huì)直接運(yùn)行,并且在運(yùn)行之后重新拋出該異常。如果該異常被 catch 代碼塊捕獲,fnally 代碼塊則在 catch 代碼塊之后運(yùn)行。在某些不幸的情況下,catch 代碼塊也觸發(fā)了異常,那么 fnally 代碼塊同樣會(huì)運(yùn)行,并會(huì)拋出 catch 代碼塊觸發(fā)的異常。在某些極端不幸的情況下,fnally 代碼塊也觸發(fā)了異常,那么只好中斷當(dāng)前 fnally 代碼塊的執(zhí)行,并往外拋異常。
1.所有異常的父類都是Throwable 2.Error異常是程序的執(zhí)行狀態(tài)無法恢復(fù)的狀態(tài),只能中止線程甚至中止JVM的異常 3.Exception是相對(duì)Error沒有這么嚴(yán)重的異常 4.Runtime Exception和Error都屬于不需要檢查的異常 5.除了Runtime Exception和Error的異常都是Check Exception異常 6.Check Exception異常都是需要顯式捕獲的異常3.Java虛擬機(jī)是如何捕獲異常的?
java虛擬機(jī)構(gòu)造異常實(shí)例非常昂貴。虛擬機(jī)需要生成該異常的棧軌跡。該操作會(huì)逐一訪問當(dāng)前線程的 Java 棧幀,并且記錄下各種調(diào)試信息,包括棧幀所指向方法的名字,方法所在的類名、文件名,以及在代碼中的第幾行觸發(fā)該異常。
既然異常實(shí)例的構(gòu)造十分昂貴,我們是否可以緩存異常實(shí)例,在需要用到的時(shí)候直接拋出呢?從語法角度上來看,這是允許的。然而,該異常對(duì)應(yīng)的棧軌跡并非 throw 語句的位置,而是新建異常的位置。
因此,這種做法可能會(huì)誤導(dǎo)開發(fā)人員,使其定位到錯(cuò)誤的位置。這也是為什么在實(shí)踐中,我們往往選擇拋出新建異常實(shí)例的原因。
異常處理器
1.來源:每個(gè)方法在編譯的時(shí)候都會(huì)生成一個(gè)異常表。異常表里面的每一個(gè)條目都代表一個(gè)異常處理器。
2.組成:
(1)from指針,to指針:代表捕獲異常的范圍,就是Try的范圍。
(2)target指針:代表處理器的開始位置,就是catch的起始位置。
(3)捕獲的異常類型。
3.捕獲異常
(1)當(dāng)程序觸發(fā)異常時(shí),Java 虛擬機(jī)會(huì)從上至下遍歷異常表中的所有條目。當(dāng)觸發(fā)異常的字節(jié)碼的索引值在某個(gè)異常表?xiàng)l目的監(jiān)控范圍內(nèi),Java 虛擬機(jī)會(huì)判斷所拋出的異常和該條目想要捕獲的異常是否匹配。如果匹配,Java 虛擬機(jī)會(huì)將控制流轉(zhuǎn)移至該條目 target 指針指向的字節(jié)碼。
(2)如果遍歷完所有異常表?xiàng)l目,Java 虛擬機(jī)仍未匹配到異常處理器,那么它會(huì)彈出當(dāng)前方法對(duì)應(yīng)的Java 棧幀,并且在調(diào)用者(caller)中重復(fù)上述操作。在最壞情況下,Java 虛擬機(jī)需要遍歷當(dāng)前線程 Java 棧上所有方法的異常表。
4.finally代碼的編譯:當(dāng)前版本 Java 編譯器的做法,是復(fù)制 fnally 代碼塊的內(nèi)容,分別放在 try-catch 代碼塊所有正常執(zhí)行路徑以及異常執(zhí)行路徑的出口中。
代碼1: Try{ Try block } catch { Catch block } finally { Finally block }
代碼2: Try { Try block Finally block } catch { Catch block Finally block } finally{ Finally block }
代碼1是我們的Java代碼,代碼2是編譯之后的Java代碼。5.Java7的 Supressed 異常以及語法糖注意:如果 catch 代碼塊捕獲了異常,并且觸發(fā)了另一個(gè)異常,那么 fnally 捕獲并且重拋的異常是哪個(gè)呢?答案是后者。也就是說原本的異常便會(huì)被忽略掉,這對(duì)于代碼調(diào)試來說十分不利。
針對(duì)上節(jié)說的會(huì)將catch的異常忽略掉,Java7引入了 Supressed 異常處理這個(gè)問題。但是使用起來還是很麻煩(沒有感受,
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/73759.html
摘要:當(dāng)運(yùn)行時(shí)系統(tǒng)遍歷調(diào)用棧而未找到合適的異常處理器,則運(yùn)行時(shí)系統(tǒng)終止。不可查異常編譯器不要求強(qiáng)制處置的異常包括運(yùn)行時(shí)異常與其子類和錯(cuò)誤。 目錄介紹 1.什么是異常 2.異常 2.1 異常的概述和分類【了解】 2.2 JVM默認(rèn)是如何處理異常的【理解】 2.3 異常處理的兩種方式【理解】 2.4 try...catch的方式處理異?!菊莆铡?2.5 編譯期異常和運(yùn)行期異常的區(qū)別【理解】...
摘要:可以被異常處理機(jī)制使用,是異常處理的核心。非檢測異常,在編譯時(shí),不會(huì)提示和發(fā)現(xiàn)異常的存在,不強(qiáng)制要求程序員處理這樣的異常??傮w來說,語言的異常處理流程,從程序中獲取異常信息。處理運(yùn)行時(shí)異常,采用邏輯合理規(guī)避同時(shí)輔助處理。 目錄 什么是Java異常? 當(dāng)一個(gè)Exception在程序中發(fā)生的時(shí)候,JVM是怎么做的呢? 當(dāng)我們編寫程序的時(shí)候如何對(duì)待可能出現(xiàn)的異常呢? 正文 1. 什么是J...
摘要:程序塊若有異常發(fā)生,程序的運(yùn)行便重點(diǎn),并拋出異常類所產(chǎn)生的對(duì)象。關(guān)鍵字我們可以使用關(guān)鍵字把可能拋出的異常顯式的標(biāo)注在方法定義的位置從而提醒調(diào)用者要注意捕獲這些異常。 ...
摘要:是那些可能在虛擬機(jī)正常運(yùn)行期間拋出的異常的超類。運(yùn)行時(shí)異常定義及其子類都被稱為運(yùn)行時(shí)異常。對(duì)于語言中的關(guān)鍵字和,虛擬機(jī)中并沒有特殊的字節(jié)碼指令去支持它們,都是通過編譯器生成字節(jié)碼片段以及不同的異常處理器來實(shí)現(xiàn)。 前言 在一些傳統(tǒng)的編程語言,如C語言中,并沒有專門處理異常的機(jī)制,程序員通常用方法的特定返回值來表示異常情況,并且程序的正常流程和異常流程都采用同樣的流程控制語句。Java語言...
閱讀 2183·2023-04-25 15:00
閱讀 2361·2021-11-18 13:14
閱讀 1188·2021-11-15 11:37
閱讀 3097·2021-09-24 13:55
閱讀 1234·2019-08-30 15:52
閱讀 2656·2019-08-29 12:35
閱讀 3371·2019-08-29 11:04
閱讀 1219·2019-08-26 12:13