JVM 內存管理是 Java 工程師進階必修課。本文系統梳理對象死亡判定(引用計數 vs 可達性分析)、四大引用強度、方法區回收、三大經典 GC 算法、七大收集器演進、分代分配規則、大對象直入老年代、動態年齡判定,構建完整知識體系,附 HotSpot 收集器組合圖譜與生產調優參數速查表。
對象存活判定
- 可達性分析(GC Roots): 栈帧局部变量、静态字段、常量、JNI 引用、同步锁持有对象。
- 引用擴展: 强引用 > 软引用 > 弱引用 > 虚引用。软引用适合缓存,弱引用适合元数据,虚引用用于跟踪回收时机。
- finalize 自救: 仅一次机会,不推荐生产使用,已废弃(JDK 9+)。
三大經典 GC 算法
| 算法 | 核心思想 | 優點 | 缺點 | 適用代 |
| 标记-清除 | 标记存活 → 统一清除 | 实现简单 | 效率低、碎片多 | 老年代 |
| 复制 | 内存对半,存活复制到另半 | 无碎片、分配快 | 浪费 50% 空间 | 新生代 |
| 标记-整理 | 标记存活 → 向一端压缩 | 无碎片、空间利用高 | 需移动对象、更新引用 | 老年代 |
七大收集器演進(HotSpot)
- Serial / Serial Old: 单线程,Client 模式默认,Stop-The-World (STW)。
- ParNew: Serial 多线程版,首款并行收集器,常与 CMS 搭配。
- Parallel Scavenge / Parallel Old: 吞吐量优先,可自适应调节堆参数(-XX:+UseAdaptiveSizePolicy)。
- CMS (Concurrent Mark Sweep): 低延迟目标,标记-清除,并发标记/清除,缺点:CPU 敏感、浮动垃圾、碎片。
- G1 (Garbage First): 区域化、面向停顿时间、混合收集、可预测停顿,JDK 9+ 默认。
- ZGC / Shenandoah: 亚毫秒级停顿、并发整理、彩色指针/读屏障,JDK 11+/12+ 实验/生产级。
內存分配與回收策略
- 优先 Eden: 新对象在 Eden 分配,TLAB 线程本地缓存加速。
- 大对象直入老年代:
-XX:PretenureSizeThreshold 避免大数组/长字符串在新生代触发频繁 GC。
- 长期存活入老年代: 年龄计数器达
MaxTenuringThreshold(默认 15)晋升。
- 动态年龄判定: Survivor 相同年龄对象总大小 > Survivor 空间 50%,直接晋升。
- 空间分配担保: Minor GC 前检查老年代最大连续可用空间是否大于新生代所有对象总大小或历次晋升平均大小,否则触发 Full GC。
生產調優速查表
-XX:+UseG1GC # JDK 9+ 推荐默认
-XX:MaxGCPauseMillis=200 # 目标停顿
-XX:InitiatingHeapOccupancyPercent=45 # 触发并发周期阈值
-XX:+UseStringDeduplication # G1 字符串去重
-XX:PretenureSizeThreshold=10M # 大对象直入老年代
-XX:MaxTenuringThreshold=15 # 晋升年龄
理解 GC 本質,方能在面對 OOM、停顿抖動、吞吐下降時,從容定位根因並給出精準調優方案。