核心假設:絕大多數對象朝生夕死(適合新生代複製算法),少數對象存活久(適合老年代標記整理)。
JVM Heap
├── Young Generation (新生代)
│ ├── Eden Space (伊甸區) ← 新對象優先分配
│ ├── Survivor 0 (From) ← Minor GC 存活對象
│ └── Survivor 1 (To) ← 輪換角色,保證一個始終為空
└── Old Generation (老年代) ← 多次 Minor GC 存活晋升
└── (Tenured Space)
Metaspace (元空間, 非堆) ← 類元數據、常量池、方法表 (JDK 8+ 替代 PermGen)
-XX:MaxTenuringThreshold (默認 15) 或 Survivor 放不下 → 直接進老年代。-XX:PretenureSizeThreshold 超過閾值繞過新生代。System.gc()、動態策略調整。| 參數 | 含義 | 生產建議 |
|---|---|---|
| -Xms / -Xmx | 堆初始/最大值 | 設為相同值,避免動態擴縮容開銷 |
| -Xmn / -XX:NewSize / -XX:MaxNewSize | 新生代大小 | 約佔堆 1/3~1/2,固定值 |
| -XX:SurvivorRatio | Eden:Survivor 比例 | 默認 8:1:1,大對象多可調大 Survivor |
| -XX:PermSize / -XX:MaxPermSize | 永久代 (JDK 7) | JDK 8+ 改用 Metaspace |
| -XX:MetaspaceSize / -XX:MaxMetaspaceSize | 元空間大小 | 根據類加載量設定,防止無限增長 |
| -Xss | 線程棧大小 | 256k~1M,過大限制線程數,過小棧溢出 |
| -XX:+HeapDumpOnOutOfMemoryError | OOM 時導出堆快照 | 生產必開,配合 -XX:HeapDumpPath |
| 收集器 | 模式 | 適用場景 | 啟用參數 | 特點 |
|---|---|---|---|---|
| Serial GC | 單線程 STW | Client 模式、單核、小堆 | -XX:+UseSerialGC | 簡單、無線程切換開銷 |
| Parallel GC (Throughput) | 多線程 STW | 多核、批處理、高吞吐優先 | -XX:+UseParallelGC | 新生代並行,老年代串行 (JDK 8+ 老年代也並行) |
| CMS (Concurrent Mark Sweep) | 並發標記+清除 | 多核、低延遲、響應時間敏感 | -XX:+UseConcMarkSweepGC | 碎片化風險,需定期 Full GC 整理,JDK 9 標記棄用 |
| G1 (Garbage First) | 分區並發+混合收集 | 大堆 (4G+)、可預測停頓、JDK 9+ 默認 | -XX:+UseG1GC | Region 劃分、優先回收垃圾多區、可配置目標停頓 |
jmap -histo:live pid 統計對象、jhat/MAT 分析堆快照、檢查大對象/集合泄漏。MaxMetaspaceSize、檢查類加載器泄漏、-XX:+CMSClassUnloadingEnabled (CMS)。-XX:MaxDirectMemorySize 限制、排查 ByteBuffer.allocateDirect 未釋放。-Xss、優化線程池、檢查系統 ulimit -u/pid_max。-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC -Xloggc:/var/log/gc-%t.log
關注指標:Young GC 頻率/耗時、Old GC 間隔/耗時、堆佔用率趨勢、晋升速率。健康系統:Young GC < 50ms、Old GC < 200ms、老年代佔用 < 70%、晋升率穩定。
「堆大小固定、新生代足夠、Survivor 能裝下存活集、避免大對象、選對收集器、日志必存、OOM 快照、壓測驗證」