生成 Heap Dump 文件
JVM 參數配置
-Xmx20m -Xms20m -Xmn10m -Xss1m
-XX:+HeapDumpOnOutOfMemoryError
-Xmx/-Xms 設為相同值,避免堆動態擴縮
-XX:+HeapDumpOnOutOfMemoryError:OOM 時自動導出快照
模擬 OOM 代碼
public class HeapOOM {
static class OOMObject {}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<>();
for (int i = 0; i >= 0; i++) { // 故意無限循環
list.add(new OOMObject());
}
}
}
MAT 分析流程
- 打開 .hprof 文件:File → Open Heap Dump
- 選擇分析報告:
- Leak Suspects Report(洩漏嫌疑報告)——首選
- Component Report(組件報告)
- Top Consumers(佔用大戶)
- 關鍵視圖:
- Histogram:按類統計實例數/淺堆/深堆
- Dominator Tree:支配者樹,直觀見「誰引用了誰」
- Path to GC Roots:對象到 GC Root 的引用鏈,定位為何無法回收
- 導出報告:MAT 可將分析結果打包為 ZIP,瀏覽器直接查看,便於團隊協作
實戰技巧
- 淺堆 vs 深堆:淺堆=對象自身大小;深堆=對象+所有被引用對象大小,反映真實保留內存
- OQL 查詢:支持類 SQL 語法精準過濾,如
SELECT * FROM java.util.ArrayList WHERE size > 1000
- 對比兩個 Dump:對比不同時點快照,發現內存增長趨勢
常見洩漏模式
| 模式 | 典型特徵 | 排查方向 |
| 集合持有失效引用 | List/Map 持續增長,元素未清理 | 檢查業務邏輯是否遺漏 remove/clear |
| 靜態集合/緩存無上限 | static Map/List 無過期策略 | 引入 Guava Cache / Caffeine 限制大小 |
| ThreadLocal 未清理 | 線程池場景下 ThreadLocal 洩漏 | 使用完畢調用 remove() |
| 類加載器洩漏 | 重複部署導致 Metaspace 增長 | 檢查 JDBC 驅動、日誌框架註冊釋放 |