在排查 OOM 之前,必須先建立 JVM 記憶體模型的心智圖:
💡 Java 8 移除 PermGen,改用 Metaspace(Native Memory),參數從
-XX:MaxPermSize改為-XX:MaxMetaspaceSize
String.intern() 濫用)# Java 8+
-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m
# Java 7/6
-XX:PermSize=64m -XX:MaxPermSize=128m
-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC(CMS/G1 預設開啟)jcmd <pid> GC.class_histogram 統計類實例數,配合 MAT/Eclipse Memory Analyzer 找 GC Root 鏈路$CATALINA_HOME/lib,減少重複載入BufferedReader、Stream API、POI SAX 模式)-Xms2g -Xmx4g -XX:NewRatio=2 -XX:SurvivorRatio=8
-Xms=-Xmx 避免動態擴縮容震盪-XX:+UseG1GC)平衡延遲/吞吐-XX:+UseParallelGC)OOM 發生
│
├─ 確認錯誤類型(Metaspace vs Heap)
│
├─ 產生 Heap Dump(-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path)
│
├─ MAT 開啟 → Histogram → 按 Retained Size 排序
│
├─ 定位佔用最大的物件 → Path to GC Roots → 找強引用鏈
│
└─ 修復代碼 / 調整參數 / 升級架構
new String()、BigDecimal、集合擴容