Java OutOfMemoryError 宕機實驗

概述

JVM OutOfMemoryError(OOME,內(nèi)存溢出錯誤)導(dǎo)致宕機的情況有多種,此處主要以超出堆最大值為例來說明OOME問題排查過程。

通過設(shè)置JVM相關(guān)參數(shù)可以在發(fā)生OOME時生成堆內(nèi)存的快照,以便后期分析問題。

JVM 主要參數(shù)

Debug 時用到的JVM參數(shù)有(具體值可以自己按需配置):

# 指定堆內(nèi)存最大值限制為10MB
-Xmx10M
# 指定堆快照生成路徑為 /test/dump,默認(rèn)文件名為:java_pidpid.hprof
-XX:HeapDumpPath=/test/dump
# 指定在發(fā)生OOME時生成堆快照文件
-XX:+HeapDumpOnOutOfMemoryError

OOME 宕機實驗

OOME 實驗代碼
package com.dotions;

import java.util.ArrayList;
import java.util.List;

public class OOMETest {
    public static void main(String[] args) {
        List<Long> list = new ArrayList<Long>();
        // 通過死循環(huán)迫使內(nèi)存溢出
        while(true) {
            list.add(new Long(0));
        }
    }
}
JVM 運行參數(shù)
-Xmx10M
-XX:HeapDumpPath=C:/oome_test_dump.hprof
-XX:+HeapDumpOnOutOfMemoryError
  • 堆最大內(nèi)存為10MB;
  • 堆快照文件生成路徑為:C:/,文件名為:oome_test_dump.hprof
  • 啟用在發(fā)生OOME時生成堆快照的配置開關(guān);
Eclipse 中的運行結(jié)果
Eclipse中的運行結(jié)果
生成的Dump文件
生成的Dump文件

Dump 文件查看

(一)使用 jvisualvm 查看

jvisualvm.exe 是JDK自帶的工具,可以對堆文件進(jìn)行查看與簡單的分析,參考文檔:http://visualvm.java.net/zh_CN/gettingstarted.html。
jvisualvm.exe 在 ** {JAVA_HOME}/bin/** 目錄下,如下圖:

jvisualvm 工具路徑
jvisualvm 界面
jvisualvm 界面
Dump 文件載入到 jvisualvm

在菜單欄中點擊 【文件】==> 【載入】,然后看到如下對話框:


文件載入對話框

先將文件類型選擇為:堆 Dump (.hprof, .)* ,再找之前OOME生成的dump文件,最后點擊【打開】按鈕進(jìn)行載入。

Dump 文件——概要信息
Dump文件的概要信息

此處可以發(fā)現(xiàn)導(dǎo)致OOME的線程是main線程;
最大的對象是ArrayList類的實例。

Dump 文件——類信息
Dump 文件中的類信息

在此處可以發(fā)現(xiàn)Long類型的實例對象占了整個堆實例的97%以上;

Dump 文件——實例數(shù)
Dump 文件中的實例數(shù)
Dump文件——OQL控制臺查詢展示
Dump文件中的OQL控制臺查詢展示
(二)使用 jhat 命令查看

jhat (Java heap analyzes toolkit)是 JDK 自帶的 Java 堆內(nèi)容分析工具??梢酝ㄟ^ jhat 命令加載 dump 文件并啟動 HTTP 服務(wù)來瀏覽 dump 文件中的內(nèi)容。

**jhat **命令介紹:


jhat 命令參數(shù)

jhat 啟動HTTP服務(wù)并加載指定dump文件:

# 指定 dump 文件路徑為:
# jhat 命令默認(rèn)端口為7000,此處指定 HTTP 服務(wù)端口為:80
jhat -port 80 c:/oome_test_dump.hprof

命令執(zhí)行結(jié)果:


jhat命令執(zhí)行結(jié)果

此時HTTP服務(wù)已啟動成功,可以在瀏覽器中輸入地址:

http://localhost/

對 dump 文件進(jìn)行瀏覽,首頁展示如下:

jhat dump 文件查看展示

對 dump 文件中實例數(shù)統(tǒng)計展示:


jhat 展示dump文件中實例數(shù)統(tǒng)計

實驗總結(jié)

該實驗中我們可以發(fā)現(xiàn),由于代碼執(zhí)行時配置的JVM參數(shù)的限制,使得最大堆內(nèi)存空間為 10MB。

而程序是死循環(huán),且list 對象沒有釋放,導(dǎo)致JVM 在GC后無法釋放堆內(nèi)存空間,從而超過了堆內(nèi)存最大值的限制,導(dǎo)致了OOME。

在實際開發(fā)和部署是,根據(jù)實際情況來設(shè)置、調(diào)整堆內(nèi)存空間限制。

以Eclipse 運行狀態(tài)為例,如下圖:

Eclipse 運行狀態(tài)

** 生產(chǎn)環(huán)境,可以對JVM 中的各個分區(qū)分別設(shè)置對應(yīng)的空間閾值。此時 OOME 問題分析就必須對應(yīng)到具體的分區(qū)上,而不是只看堆內(nèi)存空間的最大值。**

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容