Java 中常见的垃圾收集器有哪些?
- 标签:JVM、Java
🏛 业务架构师
主流收集器按业务诉求的演进线记:
- Serial:单线程,STW 久——客户端小程序;
- Parallel(吞吐派):多线程并行回收,追求总吞吐(GC 时间占比最小化),停顿可较长——批处理、离线计算:报表、ETL 跑批,整体跑完时间最优才重要;
- CMS(已废弃):首次主打低停顿(并发标记清除),但内存碎片、并发失败退化问题多——它的历史意义是把"低停顿"变成交易类业务的刚需,为 G1 铺路;
- G1(JDK 9+ 默认,主力):Region 化堆 + 可预测停顿目标(-XX:MaxGCPauseMillis)——吞吐与停顿的均衡者,4G 以上堆优势明显,大多数在线业务的默认答案;
- ZGC / Shenandoah(低停顿派):并发整理,停顿亚毫秒级且与堆大小无关——TB 级堆、延迟尖刻业务(实时风控、低延迟交易、大促核心链路)。
业务视角的选型逻辑(就一句话:按 SLA 定):
- 接口 P99 < 100ms 的在线服务:G1 起步,停顿不达标升 ZGC;
- T+1 跑批:Parallel 反而最优——别用延迟要求绑架吞吐场景;
- 堆 > 16G 且停顿敏感:直接 ZGC。
演进背后的商业逻辑:收集器从"吞吐"到"停顿"到"亚毫秒"的竞赛,动力来自在线业务对 P99 的病态敏感——延迟抖动直接换算成交易转化损失。JDK 21 后的分代 ZGC、阿里 Dragonwell 的增强,都在把"大堆 + 低停顿"这对矛盾继续压薄。
一句话:收集器没有优劣,只有与业务 SLA 的匹配度——面试时先反问业务类型再答选型,就是架构师的表达方式。
🏗 系统架构师
按演进代际讲(以 JDK 8+ 视角):
新生代收集器:
- Serial / ParNew:单线程/多线程复制算法,ParNew 曾配 CMS;
- Parallel Scavenge:吞吐量优先,可设最大 GC 时间与吞吐比例,批处理场景; 老年代:Serial Old(CMS 兜底)、Parallel Old(与 PS 搭档,吞吐型组合);
- CMS(9 废弃):并发标记清除,低停顿先驱;三色标记 + 并发清理,但内存碎片(标记清除)、并发失败退化 Serial Old、浮动垃圾。它的思想被 G1 继承;
现代主力:
- G1(9+ 默认):分 Region 化堆,整体标记整理、局部复制,可预测停顿(-XX:MaxGCPauseMillis),大堆(4~32GB)低延迟首选;Mixed GC 按回收收益挑 Region;
- ZGC(JDK 15+ 生产):染色指针 + 读屏障,并发整理,停顿亚毫秒级且与堆大小无关(TB 级堆),吞吐略低于 G1——延迟敏感的大内存服务新选择;
- Shenandoah:RedHat 的同类低停顿方案。
我的选型经验:JDK 8 老系统:Parallel(吞吐)或 CMS(低延迟,注意碎片与退化);JDK 11/17 服务:默认 G1,堆 > 16GB 且 P99 要求苛刻评估 ZGC。收集器选型就两个问题:要吞吐还是要延迟、堆多大——其余交给日志验证。
💻 全栈开发专家
按演进讲,重点落在"怎么选":
JDK 8 时代:
- Parallel Scavenge + Parallel Old:吞吐优先,全程 STW 但 GC 总时间占比低——批处理默认。
- CMS(已废弃,JDK14 移除):并发标记清除,低停顿先驱;缺点:内存碎片(标记-清除)、并发失败退化 Serial Old、CPU 敏感。
- G1(JDK9+ 默认):region 化分代,可预测停顿(
-XX:MaxGCPauseMillis),兼顾吞吐与延迟,大堆(6G+)友好。
JDK 11+:
- ZGC(JDK15+ 生产可用,JDK21 分代 ZGC):染色指针 + 并发整理,停顿亚毫秒级且与堆大小无关(TB 级堆也 <1ms),代价吞吐略降 5~10%。
- Shenandoah:与 ZGC 同代的并发整理器,RedHat 系。
我的选型决策树:
text
JDK 8 + 小堆(<4G) 在线服务 → CMS(还在用的老系统)或直接 G1
JDK 8 批处理 → Parallel
JDK 11/17 在线服务 → G1(默认即最优解,别瞎调)
超大堆 / P99 要求 <10ms(风控、网关)→ ZGC实战提醒:换收集器必须压测(吞吐/延迟曲线,不是单指标);ZGC 注意内存占用略高(染色指针的多重映射 + 浮动垃圾);老系统从 CMS 迁 G1 重点看 Humongous 对象(region 一半大小的大对象直接进老年代,是迁移后 Full GC 的头号原因)。