跳到主要內容

Java heap dump 分析流程

雖然 Java 現在已經有很強大的 GC (特別是Java 11後的 ZGC)
Memory leak 依然是個 Java 開發者得了解的議題
Memory leak 並不只在寫出持續無法被回收的物件
若是段落內的流程正確,但設計時的尖峰使用量估計錯誤,也可能讓 JVM 運行時碰到 OOM
了解記憶體分析的流程才能將架構調整得更合適

首先我們需要產生記憶體使用的報告,才能進行後續分析

在 JVM 的運行參數可以加上下列內容
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=log\

XX:HeapDumpPath 指定碰上 OOM 時要生成的 heap dump 目錄
設定好之後,我們就能在環境發生 OOM 時到目錄撈出當時間點的報告

當然只有在 JVM 崩潰時才找問題實在是太被動了
VisualVM 是個免費而且強大的工具
他整合了許多的 JVM 內建的工具,並產生即時的分析內容
https://visualvm.github.io/

Windows 環境下載了正確的 VisualVM 版本後
可以在 bin 目錄下面找到執行檔
不過先別急著開
他預設值行時會找註冊表中的 oracle JDK
使用 openJDK 的開發者請先到 etc 目錄編輯 visualvm.conf 這個檔案
找到 #visualvm_jdkhome="/path/to/jdk" 這行
把開頭的#去掉啟用設定,並把路徑設為 openJDK 路徑

開啟之後可以看到每一個執行中的 Java process
並且可以找到 thread dump、heap dump 的產生選項
如此能觀察到即時的紀錄

有了 dump 之後,接著要做的是分析
java 內建的 jmap 是其中一個選項
不過我比較建議用 eclipse 的 MAT (MemoryAnalyzer)
而且最好就用單獨MAT的版本
不要用安裝 plugin 的方式整合到開發用途的 eclipse
這樣我們調整參數才比較方便,不會跟開發參數混在一起
https://www.eclipse.org/mat/downloads.php

假如 OOM 炸掉時的 heap dump 有10G
那麼我們最好開個多一些,可能 11G 的記憶體給 MAT 用
找 MAT 的設定檔 MemoryAnalyzer.ini,並修改裡面的  -Xmx 參數即可
要開這個多記憶體的原因是
分析時候需要根據 dump 還原至該時間點的記憶體中所佔有的物件
另外還需要當下 MAT 分析其中的記憶體使用

現在 Server 環境大家都很有餘裕,開個幾10G 甚至上百G記憶體也都不是那麼罕見了
不過這可能就在 heap dump 分析上會比較麻煩點
因為通常我們開發者自己的機器沒這麼多記憶體可以用
準備記憶體分配小一點的 JVM 來產出 heap dump 供分析
或是用雲端租台高配置的 server 來做分析大概會是比較合適的解法

找問題源頭時留意並不是找單個記憶體用量最大的物件就好
先從物件相關聯的物件數量以及所有關聯的物件的總記憶體用量最大的會更合適
通常難以被GC回收的物件,會是因為相關聯的 live object 太多

留言