歡迎光臨
每天分享高質量文章

如何修複Java中的VirtualMachineError

來自:唐尤華

譯自:https://jaxenter.com/java-virtual-machine-error-154691.html

即使是最好的代碼也會丟擲錯誤,對開發人員而言這意味著需要知道如何修複它們。在這篇文章中,Ram Lakshmanan 介紹了許多不同型別的 VirtualMachineError 以及如何解決這些問題,在應用程式不崩潰的前提下回到正常狀態。

 

當 Java 虛擬機遇到內部錯誤或資源限制無法運行時,就會丟擲 Java.lang.VirtualMachineError。它是 JVM 的一種自我防禦機制,用於防止整個應用程式崩潰。 在本文中,我將討論許多不同型別的 VirtualMachineError,它們各自的特點、各種觸發原因、以及幾種可能的修複方案。

1. VirtualMachineError 的型別

 

有四種不同型別的 VirtualMachineError:

 

  1. OutOfMemoryError
  2. StackOverflowError
  3. InternalError
  4. 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
赞(0)

分享創造快樂