Java垃圾回收器的选择是JVM调优中的核心环节,不同的回收器在延迟、吞吐量、内存占用等方面表现差异明显,CMS、G1、ZGC作为不同代际的代表性回收器,适配的场景各有不同。

三款垃圾回收器核心特性对比
首先通过表格梳理三款回收器的基础特性,方便快速建立整体认知:
| 回收器类型 | 设计目标 | 适用堆内存范围 | 停顿时间表现 | JDK版本支持 |
|---|---|---|---|---|
| CMS | 低延迟优先 | 中小堆(通常4G以下) | 停顿时间较短,但存在浮动垃圾和碎片问题 | JDK 1.4引入,JDK 14移除 |
| G1 | 平衡吞吐量与延迟 | 中大堆(4G到上百G) | 可预测停顿时间,默认最大停顿200ms | JDK 7引入,JDK 9成为默认回收器 |
| ZGC | 超低延迟优先 | 超大堆(支持TB级别) | 停顿时间不超过10ms,与堆大小无关 | JDK 11引入,JDK 15成为生产可用 |
CMS垃圾回收器解析
CMS全称为Concurrent Mark Sweep,是一款基于标记清除算法的并发垃圾回收器,核心目标是减少应用停顿时间。
工作流程
CMS的回收过程分为以下几个阶段:
- 初始标记:标记GC Roots直接关联的对象,需要短暂停顿
- 并发标记:与用户线程一起运行,标记所有可达对象
- 重新标记:修正并发标记期间因用户线程运行导致的标记变动,需要停顿
- 并发清除:与用户线程一起运行,清除不可达对象
优缺点与适用场景
CMS的优势是停顿时间短,适合对响应时间敏感的中小堆应用,比如传统的Web服务、接口调用类应用。但缺点也比较明显:
- 采用标记清除算法,会产生内存碎片,长期运行可能需要Full GC整理碎片
- 并发阶段会占用部分CPU资源,对CPU密集型应用不友好
- 存在浮动垃圾,无法处理并发阶段新产生的垃圾,可能导致Concurrent Mode Failure触发Full GC
启用CMS的JVM参数配置示例:
// 启用CMS垃圾回收器 -XX:+UseConcMarkSweepGC // 设置初始堆大小 -Xms2g // 设置最大堆大小 -Xmx2g // 设置新生代大小 -Xmn512m
G1垃圾回收器解析
G1全称为Garbage First,是一款面向服务端应用的垃圾回收器,不再划分固定的新生代、老年代,而是将堆划分为多个大小相等的Region,优先回收垃圾最多的Region。
核心设计
G1的核心特性包括:
- 可预测的停顿时间模型,用户可以指定最大停顿时间目标,G1会尽量在这个时间内完成回收
- 采用标记整理算法,不会产生内存碎片
- 支持新生代和老年代的动态划分,Region的角色可以动态变化
适用场景
G1适合堆内存较大、需要平衡吞吐量和延迟的应用,比如大数据处理服务、中大型Web应用。如果你的应用堆内存超过4G,且对停顿时间有一定要求,G1是优先选择。
启用G1的JVM参数配置示例:
// 启用G1垃圾回收器 -XX:+UseG1GC // 设置最大停顿时间目标,单位毫秒 -XX:MaxGCPauseMillis=200 // 设置堆内存大小 -Xms8g -Xmx8g
ZGC垃圾回收器解析
ZGC是一款可扩展的低延迟垃圾回收器,设计目标是将停顿时间控制在10ms以内,且停顿时间不会随着堆内存增大而增加。
核心技术
ZGC通过以下技术实现超低延迟:
- 并发标记、并发转移、并发引用处理,几乎所有阶段都与用户线程并发执行
- 使用染色指针和读屏障技术,不需要额外的卡表等数据结构
- 支持TB级别的堆内存,适合超大内存的应用场景
适用场景
ZGC适合对延迟要求极高的应用,比如金融交易系统、实时数据分析系统,或者堆内存超过几十G甚至上百G的应用。不过ZGC对CPU资源有一定要求,且部分JDK版本的特性还在迭代完善中。
启用ZGC的JVM参数配置示例:
// 启用ZGC垃圾回收器 -XX:+UseZGC // 设置堆内存大小 -Xms16g -Xmx16g // JDK 15及以上版本可以设置ZGC的停顿时间目标 -XX:ZCollectionInterval=5
选型决策指南
可以根据以下几个维度判断选择哪款回收器:
- 如果应用堆内存小于4G,且对延迟敏感,同时使用的JDK版本低于14,可以选择CMS
- 如果应用堆内存4G到上百G,需要平衡吞吐量和延迟,优先选择G1,尤其是JDK 9及以上版本,G1已经是默认回收器
- 如果应用堆内存超过百G,或者对延迟要求极高,停顿时间需要控制在10ms以内,选择ZGC
- 如果是CPU密集型应用,尽量避免选择并发阶段占用资源较多的CMS和ZGC,优先选择G1
常见问题解答
为什么JDK 14移除了CMS?
因为CMS的设计存在固有缺陷,比如内存碎片、浮动垃圾问题,且维护成本较高,G1已经可以覆盖CMS的大部分适用场景,甚至有更好的表现,所以官方移除了CMS。
ZGC可以完全替代G1吗?
目前还不能,ZGC对CPU资源的要求更高,且在小堆场景下的表现不如G1,同时部分特性还在迭代中,小堆、中等延迟需求的场景还是优先选择G1。
选型时建议先根据业务场景初步选择,再通过压测验证不同回收器在真实业务负载下的表现,结合GC日志和性能指标做最终决策。