java垃圾收集器演进围绕回收效率、内存利用率、停顿时间三大约束持续权衡:从serial到分代收集,再到cms、g1,最终发展为zgc与shenandoah,逐级突破停顿瓶颈,适配硬件与业务需求变化。

Java垃圾收集器的演进不是技术堆砌,而是围绕三个刚性约束持续权衡的结果:回收效率、内存利用率、停顿时间。每一次关键升级,都对应着硬件发展、应用规模变化和业务对响应延迟的新要求。
从串行到分代:解决单核小内存时代的根本矛盾
早期JDK(1.0–1.4)只提供Serial收集器,采用标记-清除算法,全程STW(Stop-The-World),适合单核CPU和几十MB堆内存的小型应用。但随着对象创建频率上升,频繁Full GC导致应用卡顿严重。分代收集由此成为转折点——它基于“弱分代假说”:98%以上对象朝生夕死,只有极少数能活过几次Minor GC。HotSpot据此把堆划为年轻代(Eden + 两个Survivor)和老年代,分别用复制算法(高效清理短命对象)和标记-整理算法(应对长生命周期对象),大幅降低每次GC扫描范围和耗时。
从并发到分区:应对多核与大堆的双重挑战
进入JDK 5–8,多核普及+Web应用堆内存升至GB级,CMS和G1先后登场:
- CMS以“低停顿”为目标,用并发标记-清除,在老年代回收时尽量让用户线程与GC线程并行;但它不整理内存,长期运行易碎片化,最终触发Full GC反而更卡。
- G1放弃固定代际边界,把堆划分为2048个大小相等的Region,按垃圾密度优先回收(Garbage-First),通过增量式处理+预测模型(-XX:MaxGCPauseMillis)把停顿控制在合理区间,真正实现“可预测”。
从毫秒到亚毫秒:ZGC与Shenandoah重新定义低延迟边界
JDK 9之后,超大堆(TB级)、实时风控、高频交易等场景要求GC停顿必须压到毫秒甚至亚毫秒级。ZGC(JDK 11引入)和Shenandoah(OpenJDK 12引入)不再依赖“分代”或“分区”的局部优化,而是从内存访问机制底层突破:
- ZGC用染色指针(Colored Pointer),在对象引用中直接编码标记状态,所有标记、转移、重映射操作全部并发执行,停顿与堆大小无关,稳定控制在10ms内。
- Shenandoah用转发指针(Brooks Pointer),在对象头前插入一层间接引用,使对象移动过程对用户线程透明,同样实现几乎无感的GC停顿。
选择逻辑比参数更重要:没有银弹,只有适配
面试中常被问“该用哪个收集器”,答案不在背诵特性,而在理解取舍:
- 小内存(≤2GB)、吞吐优先 → Serial 或 Parallel(后者多线程加速,但STW更长)
- 中等堆(4–16GB)、平衡停顿与吞吐 → G1(默认推荐,调优成熟)
- 超大堆(≥64GB)、严苛延迟要求(
- 老系统、CMS遗留配置 → 注意JDK 14起CMS已被移除,必须迁移
真正决定效果的,是结合业务特征做验证:比如高分配率服务更适合G1的增量回收;而长周期批处理任务可能Parallel更稳。算法演进史,本质是工程现实倒逼理论创新的过程。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











