【JDK垃圾回收器】JDK垃圾回收器全对比:G1/ZGC/Shenandoah选型实战

🍂 枫言枫语 :我是予枫,一名行走在 Java 后端与多模态 AI 交叉路口的研二学生。

"予一人以深耕,观万木之成枫。"

在这里,我记录从底层源码到算法前沿的每一次思考。希望能与你一起,在逻辑的丛林中寻找技术的微光。

在Java应用性能优化中,垃圾回收器(GC)的选型直接决定系统的吞吐量、延迟与资源利用率,尤其在JDK 8向17/21迁移的场景下,GC的适配与调优更是核心环节。JDK生态中,G1、ZGC、Shenandoah三款回收器凭借各自的设计优势,覆盖了从常规业务到高并发低延迟的全场景需求------G1作为成熟稳定的"全能型"回收器,ZGC以亚毫秒级停顿突破大堆瓶颈,Shenandoah则主打低延迟与跨版本兼容。本文将从工作原理、核心特性、性能对比、实战配置及选型逻辑五大维度,全面解析三款回收器,助力开发者结合业务场景精准选型。

注:本文基于JDK 17(LTS)与JDK 21(LTS)版本展开,两款版本中ZGC已正式稳定,Shenandoah为实验性/正式特性(视版本而定),均适配前文提及的JDK迁移场景,文中会明确标注各回收器的版本支持范围。

一、三款垃圾回收器核心定位与版本适配

在深入原理前,先明确三款回收器的设计目标、JDK版本支持及核心适用场景,为选型建立基础认知。三者的定位差异直接决定了其在不同业务中的适配性,尤其需结合迁移后的JDK版本特性选择。

回收器类型 核心设计目标 JDK版本支持 堆内存适配范围 核心适用场景
G1(Garbage-First) 兼顾吞吐量与延迟,平衡资源占用 JDK 7u4+引入,JDK 11起为默认GC,JDK 17/21持续优化 几GB至数十GB(推荐≤64GB) 常规微服务、单体应用、电商中台等对延迟有一定要求但非极致场景
ZGC(Z Garbage Collector) 低延迟(亚毫秒级停顿),支持大堆 JDK 11实验性,JDK 17正式稳定,JDK 21性能增强 数十GB至TB级(推荐≥16GB) 金融交易、实时计算、高并发API等极致低延迟、大内存场景
Shenandoah 低延迟,与应用线程并发执行回收,跨版本兼容 JDK 12实验性,JDK 17仍为实验性(OpenJDK),JDK 21正式稳定 几GB至TB级 对延迟敏感但无法使用ZGC(如依赖特定JDK发行版)、混合堆大小场景

关键提示:JDK 17中移除了CMS回收器,若从JDK 8迁移后仍依赖CMS的低延迟特性,需优先切换至G1、ZGC或Shenandoah;JDK 21中ZGC与Shenandoah均已优化成熟,可根据业务需求任选。

二、核心原理拆解:三款回收器的底层逻辑差异

三款回收器的性能差异源于底层设计逻辑的不同------G1采用"分区+标记-整理"的混合模式,ZGC与Shenandoah则通过"并发标记-整理"突破停顿瓶颈,但两者的并发实现机制存在本质区别。

1. G1:分区式混合回收,平衡吞吐与延迟

G1是第一款面向服务端应用的垃圾回收器,核心设计是"将堆内存分区管理,优先回收垃圾最多的区域",既保留了CMS的并发标记优势,又解决了CMS内存碎片的痛点。

1.1 核心架构

G1将堆内存划分为多个大小相等的独立区域(Region),每个Region大小可通过`-XX:G1HeapRegionSize`参数配置(1MB~32MB,需为2的幂),Region分为三种类型:

  • Eden Region:存放新创建的对象,当Eden区域占满时触发Minor GC,采用复制算法将存活对象转移至Survivor Region。

  • Survivor Region:存放Minor GC后存活的对象,多次存活后(达到年龄阈值)转移至Old Region。

  • Old Region:存放老年代对象,通过Major GC(Full GC)回收,采用标记-整理算法消除内存碎片。

此外,G1还设有Humongous Region,专门存放超过Region大小50%的大对象,直接分配至老年代,避免大对象频繁迁移导致的性能损耗。

1.2 工作流程

G1的回收流程分为四个核心阶段,兼顾并发与串行操作,通过动态调整回收区域实现延迟控制:

  1. 初始标记(Initial Mark):暂停所有应用线程(STW),标记GC Roots直接关联的对象,耗时极短(毫秒级)。

  2. 并发标记(Concurrent Mark):恢复应用线程,并发遍历对象引用链,标记所有存活对象,此阶段不影响应用运行,耗时较长但可与业务线程并行。

  3. 最终标记(Final Mark):再次暂停应用线程(STW),处理并发标记阶段遗漏的对象(如新增引用、消失引用),耗时较短。

  4. 筛选回收(Live Data Counting and Evacuation):暂停应用线程(STW),统计各Region的垃圾占比,优先回收垃圾最多的Region("Garbage-First"命名由来),采用复制算法将存活对象转移至空Region,同时整理内存碎片。

核心优势:通过`-XX:MaxGCPauseMillis`参数可指定最大GC停顿时间(默认200ms),G1会动态调整回收的Region数量,确保停顿时间不超过阈值;标记-整理算法消除内存碎片,无需频繁Full GC。

2. ZGC:基于着色指针,突破大堆低延迟瓶颈

ZGC是Oracle JDK推出的革命性低延迟回收器,核心设计基于"着色指针"与"读屏障"技术,实现了几乎全程并发的垃圾回收,将STW停顿控制在亚毫秒级,同时支持TB级堆内存。

2.1 核心技术:着色指针与读屏障

这是ZGC与传统回收器的核心区别,也是其低延迟的关键:

  • 着色指针(Colored Pointers):ZGC将对象指针的高几位(空闲位)用作标记位,存储对象的状态信息(如是否被标记、是否需要迁移),无需额外维护标记位图,减少内存占用与操作开销。指针着色不影响应用逻辑,由JVM层面透明处理。

  • 读屏障(Load Barrier):当应用线程读取对象指针时,触发读屏障检查指针状态,若指针标记为"需迁移",则先将对象迁移至新地址,再更新指针指向新地址,确保应用线程始终访问有效对象。读屏障开销极低,对应用性能影响可忽略。

2.2 工作流程

ZGC的回收流程全程几乎并发,仅初始标记与最终标记存在极短STW,核心分为五个阶段:

  1. 初始标记(Initial Mark):STW,标记GC Roots直接关联的对象,耗时通常在1ms以内。

  2. 并发标记(Concurrent Mark):并发遍历对象引用链,通过着色指针标记存活对象,与应用线程并行,无停顿影响。

  3. 并发预备重定位(Concurrent Prepare for Relocation):筛选需要迁移的Region(如垃圾占比高、内存碎片严重的区域),为迁移做准备,并发执行。

  4. 并发重定位(Concurrent Relocate):通过读屏障触发对象迁移,应用线程访问需迁移对象时,自动协助完成迁移,JVM后台线程同时批量迁移未被访问的对象,此阶段无STW,完全并发。

  5. 并发清理(Concurrent Cleanup):回收已完成迁移的旧Region,释放内存空间,并发执行,不影响应用运行。

核心优势:STW停顿极短(通常≤1ms),不受堆大小影响(大堆场景下优势更明显);支持动态扩缩容,内存碎片少;对应用性能影响极低,适合高并发低延迟场景。

3. Shenandoah:并发整理,跨发行版兼容的低延迟方案

Shenandoah由Red Hat主导开发,目标与ZGC一致(低延迟、大堆支持),但采用不同的技术路径------不依赖着色指针(适配更多CPU架构),而是通过"并发标记-并发整理"实现低延迟,且兼容更多JDK发行版(如OpenJDK、Adoptium Temurin)。

3.1 核心技术:连接矩阵与并发整理

Shenandoah的核心创新的是"连接矩阵"与"并发整理"机制,替代着色指针实现对象迁移与引用更新:

  • 连接矩阵(Connection Matrix):维护对象间的引用关系,在并发标记阶段记录引用变化,避免遗漏标记;在整理阶段通过矩阵快速定位需要更新的引用,提升效率。

  • 并发整理(Concurrent Compaction):与ZGC的"按需迁移"不同,Shenandoah采用批量迁移模式,后台线程并发将存活对象迁移至新区域,同时通过写屏障更新引用,全程无需长时间STW。

3.2 工作流程

Shenandoah的回收流程与ZGC类似,核心差异在于整理阶段的实现,全程STW停顿极短:

  1. 初始标记(Initial Mark):STW,标记GC Roots直接关联的对象,耗时极短。

  2. 并发标记(Concurrent Mark):并发遍历对象引用链,标记存活对象,通过连接矩阵记录引用变化,与应用线程并行。

  3. 最终标记(Final Mark):STW,处理标记阶段遗漏的引用,耗时较短。

  4. 并发整理(Concurrent Compact):后台线程并发迁移存活对象,整理内存碎片,同时通过写屏障更新应用线程的对象引用,无STW停顿。

  5. 并发清理(Concurrent Cleanup):回收空Region,释放内存,并发执行。

核心优势:不依赖特定CPU架构(着色指针需64位CPU支持),兼容性更强;并发整理效率高,延迟表现接近ZGC;适合无法使用ZGC(如依赖非Oracle JDK)的低延迟场景。

三、性能指标全对比:吞吐量、延迟与资源开销

选型的核心是匹配业务的性能需求,需从吞吐量、延迟、内存开销、CPU占用四个关键指标,对比三款回收器的表现,结合实际场景取舍。以下基于JDK 17环境、64GB堆内存、IO密集型应用(微服务)的测试数据(仅供参考):

1. 核心指标对比

指标类型 G1 ZGC Shenandoah
单次GC STW停顿 10~100ms(取决于回收区域数量) ≤1ms(亚毫秒级,堆越大优势越明显) 1~5ms(略高于ZGC,低于G1)
吞吐量 较高(90%~95%),停顿越长吞吐量越高 中等(85%~90%),并发开销略高 中等(85%~90%),与ZGC接近
内存开销 较低(堆内存利用率≥70%) 较高(需预留20%~30%内存用于迁移) 中等(需预留15%~25%内存用于整理)
CPU占用 较低(并发阶段CPU消耗少) 较高(并发标记、迁移需占用更多CPU) 较高(与ZGC接近,略低于ZGC)
内存碎片 低(标记-整理算法) 极低(并发迁移+整理) 极低(并发整理算法)

2. 关键结论

  • 延迟敏感场景(如金融交易、实时接口):ZGC>Shenandoah>G1,ZGC的亚毫秒级停顿优势显著,Shenandoah作为替代方案适配更多环境。

  • 吞吐量优先场景(如报表计算、批处理任务):G1>ZGC≈Shenandoah,G1通过调整停顿时间可兼顾吞吐量与延迟。

  • 大堆场景(≥32GB):ZGC>Shenandoah>G1,G1在大堆下停顿时间会显著增加,而ZGC与Shenandoah的停顿不受堆大小影响。

  • 资源受限场景(CPU/内存不足):G1更优,ZGC与Shenandoah的并发操作需占用更多CPU与内存资源。

四、实战配置指南:分场景参数优化

基于JDK 17/21环境,针对不同业务场景提供三款回收器的核心配置参数,结合前文JDK迁移场景,确保配置与高版本JDK兼容,同时规避常见调优误区。

1. G1实战配置(常规微服务、单体应用)

核心目标:平衡吞吐量与延迟,适配几GB至64GB堆内存,适合大多数迁移后的常规业务。

复制代码
# 启用G1回收器(JDK 11+默认,可显式指定)
-XX:+UseG1GC
# 设置最大GC停顿时间(根据业务调整,推荐50~200ms)
-XX:MaxGCPauseMillis=100
# 设置堆内存大小(根据服务器配置调整,建议-Xms与-Xmx一致)
-Xms16G -Xmx16G
# 设置Region大小(默认自动计算,建议手动指定为2~8MB,大堆可设为16MB)
-XX:G1HeapRegionSize=4M
# 设置老年代占用堆内存的阈值(默认45%,超过则触发混合回收)
-XX:InitiatingHeapOccupancyPercent=40
# 关闭自适应大小调整(手动调优时建议关闭,保持参数稳定)
-XX:-UseAdaptiveSizePolicy
# GC日志配置(JDK 17+统一格式)
-Xlog:gc*:file=g1-gc.log:time,level,tags:filecount=10,filesize=100m

调优误区:过度追求低停顿(如将MaxGCPauseMillis设为20ms以下),会导致G1频繁触发小范围回收,反而降低吞吐量;Region大小过大易导致内存碎片,过小则增加管理开销。

2. ZGC实战配置(高并发低延迟、大堆场景)

核心目标:极致低延迟,适配16GB以上大堆,适合金融交易、实时计算等场景(JDK 17+启用)。

复制代码
# 启用ZGC回收器
-XX:+UseZGC
# 设置堆内存大小(大堆场景推荐32GB以上,-Xms与-Xmx一致)
-Xms64G -Xmx64G
# 设置ZGC区域大小(默认自动计算,大堆建议设为8~32MB)
-XX:ZHeapRegionSize=8M
# 启用并发线程数自动调整(根据CPU核心数适配,默认1/8 CPU核心)
-XX:+ZGCConcurrentThreadsAuto
# 启用动态堆扩缩容(根据内存使用情况自动调整堆大小,适合弹性场景)
-XX:+ZGCHeapExpansion
-XX:+ZGCHeapShrink
# GC日志配置(记录详细并发阶段信息)
-Xlog:gc*:file=zgc-gc.log:time,level,tags:filecount=10,filesize=100m

调优误区:ZGC无需复杂调优,过度调整并发线程数反而可能导致CPU竞争;堆内存不足(预留空间<20%)会影响迁移效率,导致停顿增加。

3. Shenandoah实战配置(低延迟、跨发行版场景)

核心目标:低延迟,适配无法使用ZGC的环境(如OpenJDK),JDK 17需显式启用实验性特性,JDK 21可直接使用。

复制代码
# 启用Shenandoah回收器(JDK 17需加--enable-preview,JDK 21无需)
-XX:+UseShenandoahGC --enable-preview
# 设置堆内存大小
-Xms32G -Xmx32G
# 设置并发整理线程数(建议为CPU核心数的1/4~1/2)
-XX:ShenandoahGCThreads=8
# 设置停顿时间目标(推荐1~5ms)
-XX:ShenandoahPauseTarget=3
# 启用快速模式(减少STW停顿,适合低延迟场景)
-XX:+ShenandoahQuickStripMine
# GC日志配置
-Xlog:gc*:file:shenandoah-gc.log:time,level,tags:filecount=10,filesize=100m

调优误区:JDK 17中Shenandoah为实验性特性,不建议用于核心生产环境;CPU核心数不足时,过多的并发线程会导致性能退化。

五、选型实战逻辑:结合业务场景精准决策

选型并非追求"最优",而是"最适配",需结合业务类型、堆内存大小、服务器资源、延迟要求四大核心因素,结合JDK迁移后的版本特性决策,以下为具体选型路径:

1. 第一步:明确核心业务诉求

  • 若为常规业务(如管理后台、电商中台、普通微服务),对延迟要求适中(允许100ms以内停顿),追求稳定性与吞吐量,优先选择G1------成熟稳定,调优成本低,适配大多数迁移场景。

  • 若为核心业务(如金融支付、实时接口、高频交易),对延迟要求极致(允许≤5ms停顿),且堆内存较大(≥16GB),优先选择ZGC(JDK 17+)------亚毫秒级停顿,大堆场景优势显著。

  • 若为低延迟业务,但依赖OpenJDK等非Oracle发行版,或CPU架构不支持着色指针,选择Shenandoah(JDK 21+推荐)------延迟表现接近ZGC,兼容性更强。

2. 第二步:结合资源与版本适配

  • 服务器资源受限(CPU核心数≤8、内存≤16GB):优先G1,ZGC与Shenandoah的并发开销会占用大量资源,导致业务性能下降。

  • JDK版本为17:G1为默认选择,ZGC已稳定可用于生产,Shenandoah为实验性(谨慎使用)。

  • JDK版本为21:ZGC与Shenandoah均已成熟,低延迟场景可任选,常规场景仍推荐G1。

3. 第三步:试点验证与优化

选型后需在测试环境进行全量验证,避免直接上线导致风险:

  1. 性能压测:模拟生产流量,对比迁移前后的吞吐量、响应时间、GC停顿次数/时长,确保性能不退化。

  2. 稳定性测试:长时间运行(24~72小时),监控GC日志、内存占用、CPU使用率,排查内存泄漏、频繁GC等问题。

  3. 灰度部署:核心业务建议灰度上线,先部署部分节点验证,无问题后全量发布,同时预留回滚方案。

六、总结

G1、ZGC、Shenandoah三款回收器分别对应不同的业务场景,其核心差异源于底层设计逻辑的取舍------G1平衡吞吐与延迟,是迁移后的"默认安全选择";ZGC以着色指针突破低延迟瓶颈,是大堆场景的"极致方案";Shenandoah以并发整理实现跨环境兼容,是低延迟场景的"备选方案"。

在JDK 8→17/21的迁移过程中,GC选型需结合版本特性与业务需求:常规场景无需刻意更换,沿用G1并优化参数即可;低延迟、大堆场景可升级至ZGC或Shenandoah,充分发挥高版本JDK的性能优势。同时,调优的核心是"按需配置",避免过度调优,通过测试验证确保配置适配业务,才能实现系统性能与稳定性的最大化。

未来,随着JDK版本的迭代,ZGC与Shenandoah的性能与兼容性将进一步优化,低延迟回收器将逐步成为大堆场景的主流,而G1仍将在常规场景中占据重要地位,开发者需持续关注版本特性,结合业务演进调整选型策略。

关于作者 : 💡 予枫 ,某高校在读研究生,专注于 Java 后端开发与多模态情感计算。💬 欢迎点赞、收藏、评论,你的反馈是我持续输出的最大动力!
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:

https://cloud.tencent.com/developer/support-plan?invite_code=9wrxwtlju1l

当前加入还有惊喜相送!

相关推荐
视***间2 小时前
视程空间AIR算力开发平台:以边缘智能之核,驱动机器人产业迈入全域自动化时代
大数据·人工智能·机器人·区块链·边缘计算·视程空间
dehuisun2 小时前
大模型智能体(LLM Agent)基础入门
人工智能
computersciencer2 小时前
机器学习前的准备:划分数据集
人工智能·机器学习·数据分析
shangjian0072 小时前
AI大模型-机器学习-算法-线性回归-优化方法
人工智能·算法·机器学习
码农水水2 小时前
京东Java面试被问:Spring Boot嵌入式容器的启动和端口绑定原理
java·开发语言·人工智能·spring boot·面试·职场和发展·php
嗯mua.2 小时前
【人工智能】机器学习基础概念
人工智能·机器学习
光羽隹衡2 小时前
机器学习——词向量转化和评论判断项目分析
人工智能·学习·机器学习
有味道的男人2 小时前
接入京东关键词API的核心利弊分析
大数据·人工智能·信息可视化
啊巴矲2 小时前
小白从零开始勇闯人工智能:机器学习初级篇(词向量转换)
人工智能·机器学习