JVM 發生記憶體溢位的 8 種原因、及解決辦法

網際網路搬運工發表於2019-08-20

1.Java 堆空間
2.GC 開銷超過限制
3.請求的陣列大小超過虛擬機器限制
4.Perm gen 空間
5.Metaspace
6.無法新建本機執行緒
7.殺死程式或子程式
8.發生 stack_trace_with_native_method

1. Java 堆空間

發生頻率:5顆星

造成原因

  • 無法在 Java 堆中分配物件

  • 吞吐量增加

  • 應用程式無意中儲存了物件引用,物件無法被 GC 回收

  • 應用程式過度使用 finalizer。finalizer 物件不能被 GC 立刻回收。finalizer 由結束佇列服務的守護執行緒呼叫,有時 finalizer 執行緒的處理能力無法跟上結束佇列的增長

解決方案

  • 使用 -Xmx 增加堆大小

  • 修復應用程式中的記憶體洩漏

2. GC 開銷超過限制

發生頻率:5顆星

造成原因

  • Java 程式98%的時間在進行垃圾回收,恢復了不到2%的堆空間,最後連續5個(編譯時常量)垃圾回收一直如此。

解決方案

  • 使用 -Xmx 增加堆大小

  • 使用 -XX:-UseGCOverheadLimit 取消 GC 開銷限制

  • 修復應用程式中的記憶體洩漏

3. 請求的陣列大小超過虛擬機器限制

發生頻率:2顆星

造成原因

  • 應用程式試圖分配一個超過堆大小的陣列

解決方案

  • 使用 -Xmx 增加堆大小

  • 修復應用程式中分配巨大陣列的 bug

4. Perm gen 空間

發生頻率:3顆星

造成原因

Perm gen 空間包含:

  • 類的名字、欄位、方法

  • 與類相關的物件陣列和型別陣列

  • JIT 編譯器優化

當 Perm gen 空間用盡時,將丟擲異常。

解決方案

  • 使用 -XX: MaxPermSize 增加 Permgen 大小

  • 不重啟應用部署應用程式可能會導致此問題。重啟 JVM 解決

5. Metaspace

發生頻率:3顆星

造成原因

  • 從 Java 8 開始 Perm gen 改成了 Metaspace,在本機記憶體中分配 class 後設資料(稱為 metaspace)。如果 metaspace 耗盡,則丟擲異常

解決方案

  • 通過命令列設定 -XX: MaxMetaSpaceSize 增加 metaspace 大小

  • 取消 -XX: maxmetsspacedize

  • 減小 Java 堆大小,為 MetaSpace 提供更多的可用空間

  • 為伺服器分配更多的記憶體

  • 可能是應用程式 bug,修復 bug

6. 無法新建本機執行緒

發生頻率:5顆星

造成原因

  • 記憶體不足,無法建立新執行緒。由於執行緒在本機記憶體中建立,報告這個錯誤表明本機記憶體空間不足

解決方案

  • 為機器分配更多的記憶體

  • 減少 Java 堆空間

  • 修復應用程式中的執行緒洩漏。

  • 增加作業系統級別的限制

  • ulimit -a

  • 使用者程式數增大 (-u) 1800

  • 使用 -Xss 減小執行緒堆疊大小

7. 殺死程式或子程式

發生頻率:1顆星

造成原因

  • 核心任務:記憶體不足結束器,在可用記憶體極低的情況下會殺死程式

解決方案

  • 將程式遷移到不同的機器上

  • 給機器增加更多記憶體

  • 與其他 OOM 錯誤不同,這是由作業系統而非 JVM 觸發的。

8. 發生 stack_trace_with_native_method

發生頻率:1顆星

造成原因

  • 本機方法(native method)分配失敗

  • 列印的堆疊跟蹤資訊,最頂層的幀是本機方法

解決方案

  • 使用作業系統本地工具進行診斷


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946007/viewspace-2654317/,如需轉載,請註明出處,否則將追究法律責任。

相關文章