首頁  >  文章  >  Java  >  怎麼使用JVM捕捉Java異常? (附範例)

怎麼使用JVM捕捉Java異常? (附範例)

不言
不言轉載
2019-03-19 09:31:332533瀏覽

這篇文章帶給大家的內容是關於怎麼使用JVM捕捉Java異常? (附範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

1.異常的兩大關鍵因素

(1)拋出例外
1.明確:應用程式手動拋出例外。具體就是使用throw拋出異常
2.隱含:Java虛擬機器對於無法執行的程式碼,自動拋出例外

(推薦:Java教學

(2)捕捉異常
1.try 程式碼區塊:用來標記需要進行異常監控的程式碼。
2.catch 程式碼區塊:跟在 try 程式碼區塊之後,用來擷取在 try 程式碼區塊中觸發的某種指定類型的例外。除了聲明所捕獲異常的類型之外,catch 程式碼區塊還定義了針對該異常類型的異常處理器。在 Java中,try 程式碼區塊後面可以跟著多個 catch 程式碼區塊,來擷取不同類型的異常。 Java 虛擬機會從上到下匹配異常處理器。因此,前面的 catch 程式碼區塊所捕獲的異常類型不能覆蓋後邊的,否則編譯器會報錯。
3.fnally 程式碼區塊:跟在 try 程式碼區塊和 catch 程式碼區塊之後,用來宣告一段必須執行的程式碼。它的設計初衷是為了避免跳過某些關鍵的清理程式碼,例如關閉已開啟的系統資源。在程式正常執行的情況下,這段程式碼會在 try 程式碼區塊之後運作。否則,也就是 try 程式碼區塊觸發異常的情況下,如果該例外沒有被捕獲,fnally 程式碼區塊會直接運行,並且在運行之後重新拋出該例外。如果該異常被 catch 程式碼區塊捕獲,fnally 程式碼區塊則在 catch 程式碼區塊之後運行。在某些不幸的情況下,catch 程式碼區塊也觸發了異常,那麼 fnally 程式碼區塊同樣會運行,並會拋出 catch 程式碼區塊觸發的例外。在某些極端不幸的情況下,fnally 程式碼區塊也觸發了異常,那麼只好中斷目前 fnally 程式碼區塊的執行,並往外拋異常。

2.異常的分類

怎麼使用JVM捕捉Java異常? (附範例)

#1.所有例外的父類別都是Throwable
2.Error例外是程式的執行狀態無法恢復的狀態,只能中止線程甚至中止JVM的異常
3.Exception是相對Error沒有這麼嚴重的異常
4.Runtime Exception和Error都屬於不需要檢查的異常
5.除了Runtime Exception和Error的異常都是Check Exception異常
6.Check Exception異常都是需要明確捕獲的異常

3.Java虛擬機是如何捕獲異常的?

java虛擬機構造異常實例非常昂貴。虛擬機器需要產生該異常的堆疊軌跡。此操作會逐一存取目前執行緒的 Java 堆疊幀,並且記錄下各種偵錯訊息,包括堆疊幀所指向方法的名字,方法所在的類別名稱、檔案名,以及在程式碼中的第幾行觸發該異常。
既然異常實例的建構十分昂貴,我們是否可以快取異常實例,在需要用到的時候直接拋出呢?從語法角度來看,這是允許的。然而,此異常對應的堆疊軌跡並非 throw 語句的位置,而是新建一個異常的位置。
因此,這種做法可能會誤導開發人員,使其定位到錯誤的位置。這也是為什麼在實務上,我們往往會選擇拋出新例外實例的原因。

異常處理器
1.來源:每個方法在編譯的時候都會產生一個例外表。異常表裡面的每一個條目都代表一個異常處理器。
2.組成:
(1)from指針,to指針:代表捕獲異常的範圍,就是Try的範圍。
(2)target指標:代表處理器的起始位置,就是catch的起始位置。
(3)捕獲的例外類型。
3.捕獲異常
(1)當程式觸發異常時,Java 虛擬機會從上至下遍歷異常表中的所有條目。當觸發異常的字節碼的索引值在某個異常表條目的監控範圍內,Java 虛擬機會判斷所拋出的異常和該條目想要捕獲的異常是否匹配。如果匹配,Java 虛擬機會將控制流轉移至該條目 target 指標所指向的字節碼。
(2)如果遍歷完所有異常表條目,Java 虛擬機仍未匹配到異常處理器,那麼它會彈出當前方法對應的Java 棧幀,並且在呼叫者(caller)中重複上述操作。在最壞情況下,Java 虛擬機器需要遍歷目前執行緒 Java 堆疊上所有方法的異常表。
4.finally程式碼的編譯:目前版本 Java 編譯器的做法,是複製 fnally 程式碼區塊的內容,分別放在 try-catch 程式碼區塊所有正常執行路徑以及異常執行路徑的出口中。

代码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程式碼。

注意:如果 catch 程式碼區塊捕獲了異常,並且觸發了另一個異常,那麼 fnally 捕獲並且重拋的異常是哪一個呢?答案是後者。也就是說原本的異常便會被忽略掉,這對程式碼調試來說十分不利。

5.Java7的 Supressed 異常以及語法糖

針對上節說的會將catch的異常忽略掉,Java7引入了 Supressed 異常處理這個問題。但是使用起來還是很麻煩(沒有感受,

以上是怎麼使用JVM捕捉Java異常? (附範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除