java垃圾收集器演进本质是停顿时间、吞吐量与内存开销的权衡,分代设计为共同起点,年轻代用复制算法、老年代用标记-整理/清除,跨代引用靠卡表优化;serial与parallel系列侧重吞吐优先,cms与g1则转向并发与分区以降低停顿。

Java垃圾收集器的演进,本质是围绕“停顿时间、吞吐量、内存开销”三者权衡的持续突破。从单线程STW的Serial,到毫秒级暂停的ZGC,每一次升级都解决了一类典型场景的痛点——不是越新越好,而是匹配才关键。
分代设计:所有收集器的共同起点
现代JVM默认采用分代模型,基于“绝大多数对象朝生夕死”这一弱分代假说。堆被划分为年轻代(Eden + 两个Survivor)和老年代:
- 年轻代用复制算法:存活对象少,复制成本低,天然适合高频Minor GC
- 老年代用标记-整理或标记-清除:对象寿命长,全堆扫描代价高,是STW的主要来源
- 跨代引用通过卡表(Card Table)优化记录,避免每次GC都扫描整个老年代
串行与并行:吞吐优先的早期方案
Serial和Parallel系列面向资源受限或追求高吞吐的场景:
- Serial:单线程、无额外内存开销,适合单核CPU或小型桌面应用;新生代用复制,老年代用标记-整理
- Parallel Scavenge(吞吐量优先):多线程新生代回收,配合Parallel Old,目标是最大化CPU利用率;通过-XX:MaxGCPauseMillis不设限,而是用-XX:GCTimeRatio控制GC时间占比
- ParNew:多线程版Serial,唯一能与CMS搭配的新生代收集器,常见于CMS过渡期的老系统
并发与分区:降低停顿的技术分水岭
CMS和G1标志着从“让步式优化”转向“主动重构”:
- CMS:以“并发标记-清除”尝试消除老年代STW,但无法整理碎片,长期运行易触发Full GC;适用于响应敏感、堆不太大(
- G1:将堆划为固定大小Region,按垃圾密度选择回收子集;通过-XX:MaxGCPauseMillis设定目标停顿,兼顾可预测性与大堆支持;但Remembered Set维护开销明显,超大堆下元空间或Humongous对象仍可能引发意外停顿
ZGC与Shenandoah:真正面向低延迟的下一代
它们不再妥协于“分代+STW”框架,转而用硬件特性与新算法打破瓶颈:
- ZGC(JDK11起):使用染色指针(Colored Pointers),把标记信息直接编码在64位地址的高位;并发标记、并发转移、并发重映射全程不停顿,停顿稳定在10ms内,支持TB级堆
- Shenandoah(OpenJDK12起):用转发指针(Brooks Pointer)实现对象移动时的引用一致性,同样做到几乎无STW,停顿与堆大小无关,更适合容器化弹性伸缩环境
- 二者共性:都需要64位平台、大内存支持;不依赖分代假设,但实际仍常配合分代策略使用(如ZGC也区分年轻代/老年代Region)
选型不是追新,而是看业务真实约束:小服务用Serial或Parallel足够;Web API类应用倾向G1或ZGC;金融高频交易系统则可能直接锚定ZGC。参数调优永远建立在压测数据之上,而非理论最优。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











