1. 程式人生 > 其它 >VM 發生 OOM 的 8 種原因、及解決辦法

VM 發生 OOM 的 8 種原因、及解決辦法

1. 堆空間使用過多

原因

1、Java 堆中無法再分配物件

2、物件被引用,導致物件無法被 GC 回收

3、應用程式過度使用 finalizer。finalizer 物件不能被 GC 立刻回收。

解決方案

1、通過調節JVM引數 -Xmx 增加堆大小

2、優化程式,解決記憶體洩漏問題

注:

finalize 方法高度依賴 JVM 和 GC,當一個物件被標記後,便會被 JVM 包裝成 Finalizer 物件,然後,被 JVM 設定到 Reference 的靜態屬性 pending 中,Reference 的內部執行緒則會將這個 pending 放入到建構函式的佇列中。

Finalizer 的內部執行緒則會從佇列中取出 Finalizer 物件,並呼叫其包裝的實際物件的 finalize 方法。

所以,finalize 方法需要兩個執行緒來處理他,一個是 ReferenceHandler ,一個是 FinalizerThread。

前者負責將 Finalizer 物件放入到 Reference 佇列中,後者負責從佇列中取出 Finalizer 物件並呼叫實際物件的 finalize 方法。

同時,GC 大概也要做 2 件事情,一個是建立 Finalizer 物件,一個是將該物件設定到自己的 pending 屬性中。

pending[ˈpendɪŋ]:待定

2. GC 開銷過大

原因

1、Java不斷的

解決方案

1、通過調節JVM引數 -Xmx 增加堆大小

2、通過調節JVM引數 -XX:-UseGCOverheadLimit 取消 GC 開銷限制

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

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

原因

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

解決方案

1、通過調節JVM引數 -Xmx 增加堆大小

2、優化程式碼,不要一次性分配這麼大的陣列

4. Perm gen 空間

gen:情報

原因

Perm gen 空間包含:

1、類的名字、欄位、方法

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

3、JIT 編譯器優化

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

解決方案

1、通過調節JVM引數 -XX: MaxPermSize 增加 Permgen 大小

5. Metaspace

原因

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

解決方案

1、調節引數 -XX: MaxMetaSpaceSize 增加 metaspace 大小

2、增加伺服器的記憶體

3、檢查程式碼,可能是bug引起的

6. 發生 stack_trace_with_native_method

原因

1、native method 分配失敗

2、檢視堆疊資訊,最頂層的幀是 native method

解決方案

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

7. 殺死程序或子程序

原因

1、記憶體不足,在可用記憶體極低的情況下會殺死程序

解決方案

1、將程序遷移到不同的機器上

2、給機器增加更多記憶體

3、這是由作業系統而非 JVM 觸發的。