Java異常處理使用Throwable而不是Exception

線上問題

近期在線上系統中遇到了一個奇怪的問題,某個請求處理失敗了,但是日誌裏沒有任何錯誤信息,catch(Exception e) {}代碼塊根本沒有執行,因此直接跳過了錯誤處理邏輯,但是finally{}塊卻執行了。根據此現象我們推測出很可能是代碼塊拋出了非Exception子類的異常。果然,將catch Exception改爲catch Throwable後, 日誌中出現了java.lang.IncompatibleClassChangeError異常。因爲此異常是Error而不是Exception的子類,所以導致了出現catch{}沒有執行但finally執行了的現象。

關於Exception

異常.png
在很多入門書上都會有類似於"Exception是可恢復的而Error往往是不可恢復的系統嚴重錯誤"這樣的內容,當然,這句話本身是沒問題的,問題在於即便是Error錯誤我們也應該捕獲一下,至少要記一下日誌,如果忽略掉的話就會出現上面這種莫名其妙失敗但又找不到線索的情況。
經查,報java.lang.IncompatibleClassChangeError的原因是最近一次上線時引入了新的業務jar包,此依賴的某個傳遞依賴版本跟原有系統中的jar版本有衝突,導致JVM在執行時報錯。這個問題之所以在測試時沒有發現,還有一個原因,就是只有在執行到特定邏輯時纔會觸發,並不是每次都會出現,非常隱蔽。

如果偶爾看過Netty的代碼,你會發現Netty所有的catch, 最後都是以catch(Throwable e)結尾的,而不是Exception。我們在編碼時也應該以catch Throwable兜底, 不要再使用Exception了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章