
| 區域 | 線程共享 | 主要內容 | OOM 風險 |
|---|---|---|---|
| 程序計數器 (PC Register) | 私有 | 當前執行字節碼行號 | 無 |
| Java 虛擬機棧 | 私有 | 棧幀 (局部變量表、操作數棧、動態連接、方法出口) | StackOverflowError (深遞歸)、OOM (棧擴展失敗) |
| 本地方法棧 | 私有 | Native 方法調用 | 同 Java 棧 |
| 堆 | 共享 | 對象實例、數組、字符串常量池 (JDK 7+) | OutOfMemoryError: Java heap space |
| 方法區 / Metaspace | 共享 | 類信息、常量、靜態變量、即時編譯代碼緩存 | OutOfMemoryError: Metaspace |
| 直接內存 | 共享 | NIO DirectBuffer、Netty 等堆外內存 | OutOfMemoryError: Direct buffer memory |
| 參數 | 含義 | 建議值/策略 |
|---|---|---|
| -Xms / -Xmx | 堆初始/最大值 | 設為相同值避免震盪,通常 2G~4G (視物理內存 1/2~2/3) |
| -Xmn | 新生代大小 | 整體堆 1/3~1/2,或 -XX:NewRatio=2 (老年代:新生代=2:1) |
| -XX:SurvivorRatio | Eden:Survivor 比例 | 默認 8:1:1,大對象多可調小 (如 4:1:1) |
| -XX:MetaspaceSize / -XX:MaxMetaspaceSize | 元空間初始/最大 | 初始 256M,最大 512M~1G,防止動態擴容 Full GC |
| -Xss | 線程棧大小 | 256K~512K,深遞歸增大,高併發減小以容納更多線程 |
| -XX:+UseG1GC | 啟用 G1 收集器 | JDK 9+ 默認,大堆 (>4G) 低延遲首選 |
| -XX:MaxGCPauseMillis | 目標最大停頓 | 100~200ms,G1/ZGC 關鍵調優參數 |
| -XX:+HeapDumpOnOutOfMemoryError | OOM 時導出堆轉儲 | 生產必開,配合 -XX:HeapDumpPath=/path |
// 用完立即置 null,幫助 GC 掃描到 List<Data> hugeList = fetchHugeData(); process(hugeList); hugeList = null; // 關鍵行 // 後續代碼...
局部變量離開作用域自動釋放;長生命周期對象 (集合、緩存、靜態字段) 必須顯式清理。
new ArrayList<>(expectedSize) 避免擴容拷貝。System.gc() 僅建議,不可靠,且可能觸發 Full GC 導致長停頓。依賴分代收集器自動管理。
-XX:+DoEscapeAnalysis,默認開) 後,未逃逸對象可棧上分配、標量替換、同步消除。| 錯誤信息 | 原因 | 定位工具 | 解決方向 |
|---|---|---|---|
| Java heap space | 堆不足/洩漏 | JVisualVM、MAT、JHat | 增大堆、修復洩漏 (靜態集合未清理、監聽器未移除) |
| Metaspace | 類加載過多/動態代理 | jcmd PID VM.metaspace | 增大 MaxMetaspaceSize、檢查 CGLIB/動態類生成洩漏 |
| StackOverflowError | 遞歸過深/循環調用 | Thread Dump | 改迭代、增大 -Xss、檢查循環依賴 |
| Direct buffer memory | NIO/Netty 堆外未釋放 | JVisualVM、-XX:MaxDirectMemorySize | 顯式釋放 (Cleaner)、增大直接內存 |
| GC overhead limit exceeded | GC 耗時>98% 但回收<2% | GC 日志、JVisualVM | 增大堆、優化對象分配速率、更換收集器 |
-Xlog:gc*:file=/var/log/gc-%p-%t.log:time,uptime,level,tags:filecount=10,filesize=100m
使用 GCViewer、GCEasy、Arthas 可視化分析:Young/Full GC 頻率、耗時、內存回收率、分配速率。
JVM 優化無銀彈,核心是「理解內存模型 → 設置合理基線參數 → 壓測觀察 GC 行為 → 針對性調整代碼與參數」。建立基準測試,持續監控 GC 指標,比盲目調參更有效。