1. 什麼是Java異常?java
今天咱們來聊聊java異常,異常是致使程序中斷執行的一種指令流。咱們在提升代碼穩定性和健壯性的時候,經常會花更多的時間去考慮,代碼可能存在的異常。編碼中對可能的發生的異常先一步正確處理,就能夠確保異常不會致使程序不可用。說了這麼多異常,那麼異常是什麼呢?程序員
Java異常是一種致使程序中斷的執行指令流。它存在應用服務器硬件錯誤、程序編寫的時候未考慮數組越界、也多是網絡通訊中網絡抖動的客觀緣由致使的異常等狀況。異常多是主觀代碼設計不周全也多是客觀硬件報錯,那麼認識異常就是避免異常的第一步。咱們先從異常家族的認識開始,下面異常的族譜:數據庫
Throwable類做爲全部異常的發源,他是整個Java異常體系的超體,其下面分爲Error和Exception兩大類。編程
Error與其子類實例表明嚴重系統錯誤,應用程序沒法處理,如硬件層面的錯誤、JVM錯誤或內存不足等問題,這種錯誤發生時Java應用程序自己無力恢復。Error對象拋出時,基本上不用處理,任其傳播至JVM爲止,應用程序能作的最多留下日誌信息。數組
Exception表明程序運行時發送的各類不指望發生的事件。能夠被Java異常處理機制使用,是異常處理的核心。Exception及其子類能夠被程序處理,也就是所在應用程序中正確的處理了Exception及其子類就能提升代碼的穩定性和健壯性。服務器
Exception類下面分爲檢測異常和非檢測異常:網絡
檢測異常,是JVM強制要求程序員爲可能出現的異常作預備處理工做。JVM規定檢測異常要麼使用try-catch語句捕獲它並進行處理,要麼使用throws子句聲明並拋出它,否者javac在編譯程序會不經過。這類異常通常是程序運行環境致使的,爲了預防未知環境對程序的影響,規定程序員須要處理這類異常。函數
非檢測異常,javac在編譯時,不會提示和發現異常的存在,JVM不強制要求程序員處理這樣的異常。固然,做爲程序員咱們應該預防這樣的異常致使程序崩潰,因此建議使用try-catch-finally處理它。這類異常緣由多半是代碼寫的邏輯有問題或考慮不周全。編碼
2.當一個Exception在程序中發生的時候,JVM是怎麼作的呢?spa
對java總體異常家族有了大體的認識以後,那麼當一個Exception在程序中發生的時候,JVM是怎麼作的呢?
認識這個問題,咱們首看看JVM是如何執行java代碼的,JVM將class文件轉換爲JVM的java類。JVM爲java類創建方法表,方法表中的索引能夠引導JVM找到須要執行的方法體和JVM方法執行棧。固然,invokemethod調用執行一個方法的時候,Java虛擬機把描述該方法的棧結構置入方法執行棧棧頂,位於棧頂的方法爲正在執行的方法。 JVM會爲每個方法創建執行的堆和棧用於存放執行中的變量,若是此時程序出現一個Exception,拋出的異常先轉移給合適的異常處理語句。代碼的執行會被相應的Exception執行流接管,將方法表信息、發生異常的位置信息和方法的堆棧信息壓入Exception的堆棧,當程序中斷的時候IDE就會將Exception的堆棧信息打印出來。
若是咱們經過try…..catch….finally語句來處理異常,處理流程又是怎樣的呢?在try代碼塊中拋出的異常,代碼執行流會跳轉到catch代碼塊執行,catch代碼塊能夠對發生的異常進行補救。讓代碼迴歸到正常的執行流程。finally語句,不管在try模塊中是否發生異常,都會執行finally語句,使用finally語句主要是爲了釋放被佔用的資源,好比打開的文件或連接的通訊資源等。
整體來講,Java語言的異常處理流程,從程序中獲取異常信息。根據Java的源文件和用戶調用的包列表,JVM能夠獲取該程序包括Java API所引起的異常在內的異常處理的信息,這些信息包括:異常引起位置、異常拋出順序、引起異常的方法名和類名等。這些異常信息在程序異常的排查和修改的時候很是重要,後面會講到如何正確處理這些異常。
3.當咱們編寫程序的時候如何對待可能出現的異常呢?
一般在發生異常的時候咱們有兩種處理模型:終止與恢復。
終止模型:前提是假設錯誤很是關鍵,以致於程序沒法返回到程序正常運行軌跡,一旦異常拋出就意味着程序將中止提供服務。如:數據庫鏈接異常發生。
恢復模型:也就是異常程序發生錯誤,錯誤能夠被修復而後從新回到正常程序執行的軌跡上。例如,咱們能夠將數據庫鏈接try。。。catch置於循環中,一次鏈接不成功能夠循環下一次進行鏈接。
配合終止和恢復模型,咱們會配合使用throw和throws語法。throws關鍵字主要在方法簽名中使用,用於聲明該方法可能拋出的異常。throws 能夠理解成是一種通知行爲,沒有實際的拋出異常的動做,而僅僅是告訴調用他的上層函數,這裏可能會拋出這個異常;
throw用於在函數體內語句中,表示拋出一個實際的異常的實際動做,若是在函數內沒有捕獲並處理,那麼將會一直向上拋出這個異常直到被main()/Thread.run()拋出。
咱們瞭解了Java的異常內容以後,在程序中遵循怎樣的行業規則和大牛的經驗合理使用異常,提升代碼的穩定性呢?
下面整理了包括Effective Java異常使用指導原則和網上博客內容:
不要被這麼多規則嚇到了,不須要逐條強記他們。我對異常的理解,首先態度上要謙虛明白代碼中很難避免由於考慮不周出現的異常,因此編碼時應該採用防衛式編碼。其次在編碼處理過程當中使用try…catch…finally語句預防可能的異常,採用合適的異常處理模式對待程序可能的異常。