垃圾回收(Garbage Collection, GC)是Java生态的核心技术之一,其演进历程不仅反映了硬件性能的飞速发展,也映射了从桌面应用到云原生时代的场景变迁。本文将带你回顾JVM垃圾回收器的重要发展阶段,解析每个时代的关键技术及其背后的设计哲学。
一、单线程时代:Serial GC(JDK 1.3)
核心特点
-
单线程回收:所有GC操作由单个线程执行,触发时暂停所有应用线程(Stop-The-World, STW)。
-
分代模型:
- 年轻代:复制算法(存活对象从Eden区复制到Survivor区)
- 老年代:标记-整理算法(Serial Old)
-
适用场景:单核CPU、客户端应用(如早期Swing程序)。
历史意义
作为JVM最早的GC实现,Serial GC奠定了分代回收的基础逻辑,但其单线程模型在多核时代迅速暴露性能瓶颈。
二、并行化革命:Parallel GC(JDK 1.4~1.5)
1. Parallel Scavenge + Parallel Old
-
目标:最大化吞吐量(单位时间处理任务量)。
-
设计:
- 年轻代(Parallel Scavenge):多线程并行复制算法。
- 老年代(Parallel Old,JDK 1.5引入):多线程标记-整理算法。
-
适用场景:计算密集型任务(如离线数据分析)。
2. ParNew + CMS组合(JDK 1.5)
-
ParNew:
- 年轻代多线程回收器,专为CMS设计。
- 与Parallel Scavenge类似,但优化方向不同(低延迟优先)。
-
CMS(Concurrent Mark-Sweep) :
- 老年代并发标记-清除,减少STW时间。
- 局限性:内存碎片、并发失败时回退到Serial Old(长时间STW)。
技术突破
通过多线程并行化,显著提升吞吐量,但延迟问题(尤其是Full GC)仍未彻底解决。
三、分区时代:G1 GC(JDK 7u4~9)
核心设计
- 堆分区:将堆划分为多个等大小的Region(区域),动态管理年轻代/老年代。
- 回收策略:优先回收垃圾比例高的Region(Garbage-First),兼顾吞吐量和延迟。
优势
- 可预测停顿 :通过
-XX:MaxGCPauseMillis
参数设定目标停顿时间。 - 内存碎片控制:整体采用标记-整理算法,避免CMS的碎片问题。
历史地位
JDK 9起成为默认GC,取代CMS成为服务端应用的主流选择。
四、低延迟时代:ZGC与Shenandoah(JDK 11+)
1. ZGC(Z Garbage Collector)
-
目标:亚毫秒级停顿,支持TB级堆内存。
-
关键技术:
- 染色指针(Colored Pointers) :在指针中嵌入元数据,实现并发标记与压缩。
- 读屏障(Load Barrier) :动态修正指针状态,无需全局暂停。
-
适用场景:实时系统、云原生基础设施。
2. Shenandoah
-
核心创新:
- 并发压缩:与ZGC类似,但通过Brooks指针实现内存整理。
- 停顿时间与堆大小无关。
-
与ZGC的区别:
- Shenandoah由Red Hat主导,ZGC由Oracle开发。
- 实现细节不同(如内存屏障机制),但目标一致。
技术突破
通过并发压缩和硬件级优化(如多核并行),彻底打破"低延迟需牺牲吞吐量"的传统困局。
五、特殊用途回收器
1. Epsilon GC(JDK 11)
- 特点:只分配内存,不执行回收。
- 用途:性能测试、短生命周期任务(如CI/CD流水线)。
2. Serial Old的终局
- 历史角色:CMS的备选回收器,单线程标记-整理。
- 现状:随CMS在JDK 14中被移除,逐渐退出历史舞台。
六、演进驱动力与未来趋势
1. 核心驱动力
- 硬件发展:多核CPU、大内存、NUMA架构。
- 应用场景:从批处理到实时系统、微服务、Serverless。
- 算法创新:并发标记、染色指针、读屏障等技术突破。
2. 未来方向
- 异构计算:利用GPU/DPU加速GC任务。
- 内存层级优化:针对持久化内存(PMEM)等新硬件设计GC策略。
- 无分代模型:ZGC/Shenandoah已验证统一堆管理的可行性。
七、总结:如何选择垃圾回收器?
场景 | 推荐GC | 关键参数 |
---|---|---|
低延迟实时系统 | ZGC/Shenandoah | -XX:+UseZGC / -XX:+UseShenandoahGC |
高吞吐批处理 | Parallel GC | -XX:+UseParallelGC |
中小堆内存平衡场景 | G1 GC | -XX:+UseG1GC |
短期任务/测试 | Epsilon GC | -XX:+UseEpsilonGC |
八、演进时间线
年代 | 核心事件 |
---|---|
2000s初 | Serial GC(单线程分代) |
2004 | Parallel Scavenge + Serial Old(JDK 1.4) |
2005 | CMS + ParNew + Serial Old(JDK 1.5) |
2012 | G1 GC(实验性,JDK 7u4) |
2017 | G1成为默认(JDK 9) |
2018~2020 | ZGC/Shenandoah实验性引入(JDK 11~15) |
2023+ | ZGC成为生产环境主流(JDK 21+优化) |
结语:JVM垃圾回收器的演进是一部"与硬件赛跑,为应用赋能"的技术史诗。理解这段历史,不仅能帮助开发者优化系统性能,更能洞察未来技术的演进方向。正如Java始终"Write Once, Run Anywhere",GC技术也在不断追求"Pause Less, Serve More"的理想境界。