來自:唐尤華
譯自:https://jaxenter.com/java-virtual-machine-error-154691.html
即使是最好的程式碼也會丟擲錯誤,對開發人員而言這意味著需要知道如何修複它們。在這篇文章中,Ram Lakshmanan 介紹了許多不同型別的 VirtualMachineError 以及如何解決這些問題,在應用程式不崩潰的前提下回到正常狀態。
當 Java 虛擬機器遇到內部錯誤或資源限制無法執行時,就會丟擲 Java.lang.VirtualMachineError。它是 JVM 的一種自我防禦機制,用於防止整個應用程式崩潰。 在本文中,我將討論許多不同型別的 VirtualMachineError,它們各自的特點、各種觸發原因、以及幾種可能的修複方案。
1. VirtualMachineError 的型別
有四種不同型別的 VirtualMachineError:
- OutOfMemoryError
- StackOverflowError
- InternalError
- UnknownError
讓我們在本節中詳細回顧這些型別。
Java throwable 類層次結構
1.1 OutOfMemoryError
就像 OMG(Oh My God)的首字母縮寫一樣,OOM(OutOfMemoryError)在 DevOps 社群中非常流行。 雖然大多數 DevOps 的工程師可能認為只有一種 OutOfMemoryError,但實際上 OutOfMemoryError 有八種不同型別:
- java.lang.OutOfMemoryError:Java 堆空間
- java.lang.OutOfMemoryError:GC 開銷超過限制
- java.lang.OutOfMemoryError:請求的陣列大小超過虛擬機器限制
- java.lang.OutOfMemoryError:Permgen 空間
- java.lang.OutOfMemoryError:Metaspace
- java.lang.OutOfMemoryError:無法新建本機執行緒
- java.lang.OutOfMemoryError:殺死行程或子進
- java.lang.OutOfMemoryError:發生 stack_trace_with_native_method
觸發每種錯誤的原因各有不同。類似地,根據 OutOfMemoryError 不同的問題型別,對應的解決方案也不一樣。這裡有一份很好的檔案,用一頁紙總結了所有不同型別的 OutOfMemoryError、觸發原因和解決方案。
通常可以透過分析垃圾回收日誌和堆轉儲檔案來診斷和修複 OutOfMemoryError 錯誤。手動分析垃圾回收日誌可能會很乏味,可以考慮使用免費工具,如 GCeasy、HP Jmeter 或 IBM GC analyzer。 類似地,也可以考慮使用 HeapHero 或 Eclipse MAT 這樣的免費工具來分析堆轉儲檔案。
參見:StackOverFlowError:原因及解決方案
1.2 StackOverflowError
執行緒的堆疊儲存了執行的方法、基本資料型別值、區域性變數、物件指標和傳回值資訊,所有這些都會消耗記憶體。如果執行緒的堆疊大小超過了記憶體分配限制,那麼就會丟擲 java.lang.StackOverflowError。通常由於執行程式中有一個錯誤,在執行緒重覆遞迴呼叫同一個函式時會發生這個問題。關於如何除錯 StackOverflowError 的細節以及修複這個問題可能的解決方案,更多資訊可以看這裡。
1.3 InternalError
JVM 丟擲 java.lang.InternalError 有三個原因,虛擬機器軟體出現錯誤、系統軟體底層出現錯誤或者硬體出現故障。
然而,很少會遇到 InternalError 這樣的錯誤。要瞭解哪些特定情況可能導致 InternalError,請在 Oracle 的 Java Bug 資料庫 中搜索 InternalError。在寫這篇文章的時候(2018年12月20日),Oracle Java Bug 資料庫中僅報告了200個 InternalError,而且大多數都已經修複了,所以不必對此過於擔心。
1.4 UnknownError
當發生異常或錯誤,但 Java 虛擬機器無法報告確切的異常或錯誤時,就會丟擲 java.lang.UnknownError。UnknownError 很少出現。事實上,在 Oracle Java Bug 資料庫中搜索 UnknownError 時,只找到了2個 Bug。
參見:遠端除錯 Java 應用程式
2. 特徵
VirtualMachineError 有兩個主要特徵:
- 非受檢異常(Unchecked exceptions)
- 同步樣式與非同步樣式
讓我們在本節中討論這兩個特徵。
2.1 非受檢異常
有兩種異常型別:受檢異常和非受檢異常。
在編譯時檢查的異常稱為受檢異常。如果程式碼中的某些方法丟擲受檢異常,那麼該方法必須處理該異常或者使用 throws 關鍵字指定異常。受檢異常包括 IOException、SQLException、DataAccessException、ClassNotFoundException 等。
非受檢異常常沒有這個要求,它們不需要捕獲或者宣告丟擲。所有型別的 VirtualMachineError 都是非受檢異常。
2.2 同步樣式與非同步樣式
可以在兩種樣式下丟擲異常:同步樣式和非同步樣式。
同步異常在特定程式陳述句執行時發生,無論該程式在類似的環境中執行了多少次。同步異常的例子有 NullPointerException、 ArrayIndexOutOfBoundException 等。
非同步異常可以在任何時間點和程式陳述句的任何部分發生,異常丟擲的地方也不一樣。所有的 VirtualMachineError 都是非同步丟擲的,但有時也會同步丟擲。StackOverflowError 可能隨方法呼叫而同步丟擲,也可能隨著本地方法執行或 Java 虛擬機器資源限制非同步丟擲。類似地,OutOfMemoryError 可能在物件建立、陣列建立、類初始化和裝箱轉換時同步或非同步丟擲。
3. 參考資源
- StackOverFlowError 原因及解決方案:https://jaxenter.com/stackoverflowerror-causes-152027.html
- 遠端除錯 Java 應用程式: https://jaxenter.com/remote-debugging-java-applications-151466.html
已傳送
朋友將在看一看看到
分享你的想法…
分享想法到看一看