本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
【腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
打工人的苦,只有打工人懂。同时,职场中的牛马要上位,更是要忍受苦中苦。
和职场一样,G1 GC 熬了 15 年,才能在 JDK 27 中上位了,G1 GC 终于一统江湖了,Serial GC 彻底让位了。
根据 JEP 523 的信息,G1 GC 在 JDK 27 中成为所有环境的默认 GC,而不再局限于服务器环境。这个“迟到”的默认化历经了约 15 年的演进。15 年间,JDK 换了一茬又一茬,G1 GC 进化了再进化,终于成了默认首选。接下来,我就扯一扯 G1 GC 这一路走来的辛酸泪。
G1 GC 的发展阶段
下面这个表格,是 G1 GC 的一个大致发展时间线。
| 时期 | JDK 版本 | 关键里程碑 |
|---|---|---|
| 实验阶段 | JDK 6u14 (2009) | 首次作为体验版(Experimental)引入 |
| 正式发布 | JDK 7u4 (2011) | 正式成为官方支持的 GC,定位服务端、多核、大内存 |
| 继续打磨 | JDK 8 (2014) | Parallel GC 依然是服务端的默认霸主,G1 在后台默默打磨,修复各种内存泄漏和性能瓶颈 |
| 默认化第一步 | JDK 9 (2017, JEP 248) | 成为服务器环境的默认 GC,但小内存/单核环境仍回退到 Serial GC |
| 持续优化 | JDK 10~JDK 26 | Full GC 改为并行执行(JDK 10);JDK 14 增强 NUMA 感知,再到 JDK 26 的 JEP 522 通过减少同步开销大幅提升吞吐量。这个过程还伴随着并发标记优化;ZGC/Shenandoah 崛起形成竞争 |
| 终极默认化 | JDK 27 (JEP 523) | 成为所有环境的默认 GC,彻底取代 Serial GC 在小内存/单核场景的地位 |
核心演进逻辑
G1 的设计初衷是取代 CMS,解决其“内存碎片”和“不可控停顿”问题。它采用物理分区、逻辑分代的 Region 模型,通过 Mixed GC 和停顿预测模型(Pause Time Goal)来平衡吞吐与延迟。
但早期 G1 在小内存(<< 1792MB)或单核环境下,相比 Serial GC 存在明显劣势。
- 内存占用高:Remembered Set(RSet)等元数据结构额外消耗 10%-20% 堆内存
- 吞吐量低:并发标记和写屏障带来额外 CPU 开销
- 启动慢:复杂的分区初始化逻辑
因此 JDK 9 默认化时做了妥协,JVM 在检测到“受限环境”时自动回退到 Serial GC。
为什么迟到了这么多年?
G1 从 JDK 7u4 发布到 JDK 27 全面默认化,间隔约 15 年。这其中延迟的核心原因是工程上的“不可能三角”,即在吞吐、延迟、内存占用之间难以同时达标。
Oracle 官方在 JEP 523 的动机中明确表示,现在的 G1 已经“脱胎换骨”,足以在所有场景下替代 Serial。
- 吞吐量追平:得益于 JDK 26 中 JEP 522 对写屏障同步的优化,G1 的最大吞吐量已经逼近 Serial GC。
- 内存占用大幅瘦身:经过近几个版本的持续优化,G1 的原生内存使用量已经降低到了与 Serial GC 相当的水平。
- 延迟依然碾压:G1 通过增量回收(Incremental)老年代内存,避免了 Serial GC 动辄整个堆的 Full GC,因此最大延迟表现始终优于 Serial。
另外,还有一个隐含的原因官方未说,那就是现在大内存越来越多。更何况,既然 G1 现在各项指标都能打,且能让 JVM 的行为更加统一(开发者再也不用去猜“我的容器到底默认用了哪个 GC”),Serial 的退位自然是水到渠成。
文章配图参见 https://mp.weixin.qq.com/s/F_bNStJRD7Zo_kiSZKLHRg。
小内存场景
在小内存场景,Serial GC 优势长时间以来都难以撼动。
Serial GC 虽然停顿时间长,但在小堆(<< 1GB)和单核环境下。
- 零并发开销:没有并发标记线程,不抢 CPU
- 内存极简:无需 RSet、Card Table 等复杂结构
- 吞吐极高:STW 期间应用线程完全暂停,GC 独占 CPU
现在,JEP 523 明确指出,直到近期 JDK 版本通过减少同步开销(JEP 522)和降低原生内存使用,G1 的吞吐量才接近 Serial(注意,这里是接近),内存占用才与之相当。
并发收集器的竞争倒逼 G1 进化
ZGC(JDK 11)和 Shenandoah(OpenJDK 12)的崛起,迫使 G1 必须持续优化。
- ZGC 承诺 <10ms 停顿,但早期不支持分代、内存开销大(+15-30%)
- Shenandoah 低延迟但长期实验性,直到 JDK 25 才 finalized
于是,G1 以来了一些关键改进,主要包括下面两点。
- Remembered Set 内存削减 62%(64GB 堆上从 2GB 降至 0.75GB)
- Mixed GC 区域选择优化,减少停顿尖刺
这些改进让 G1 终于能在受限环境中与 Serial GC 打平。
保守的默认策略
Oracle/OpenJDK 对“默认 GC”的变更极其谨慎。默认 GC 影响数百万应用,任何性能回退都会引发大规模生产事故。JDK 9 的“服务器环境默认化”本身就是一次渐进式试验,观察了 8 年才敢推进到全环境。
G1 GC 现存的缺点与潜在替代者
尽管成为默认 GC,G1 并非完美。其短板和替代者的定位我整理汇总如下。
G1 的核心缺点
见下面这个表格。
| 缺点 | 具体表现 | 影响场景 |
|---|---|---|
| STW 停顿仍存在 | 典型 20-200ms,大堆最坏可达 500ms | 金融交易、实时系统、p999 敏感型微服务 |
| CPU 开销较高 | 写屏障(Write Barrier)和并发标记持续消耗 CPU | CPU 饱和的批处理、嵌入式设备 |
| 内存开销 | 即使 JDK 25 优化后,RSet 仍占显著内存 | 容器/K8s 小内存 Pod(<<4GB) |
| 调优复杂度 | Region 大小、CSet 选择、IHOP 阈值等参数需经验 | 缺乏专职运维的小团队 |
| Full GC 兜底 | 极端情况下退化为串行 Full GC,停顿剧增 | 内存泄漏、突发流量 |
替代者 ZGC 与 Shenandoah
2026 年的 GC 格局已形成“三足鼎立”之势,见下面这个对比表格。
| 维度 | G1 | ZGC (Generational) | Shenandoah (Generational) |
|---|---|---|---|
| 停顿时间 | 20-200ms 典型 | 0.1-0.5ms 典型,<<1ms 最坏 | 1-5ms 典型,~10ms 偶发 |
| 内存开销 | 基准 (~10% headroom) | +15-30%(无压缩指针) | +10-20%(支持压缩指针) |
| 吞吐量 | 基准(最高) | 5-15% 低于 G1 | 5-10% 低于 G1 |
| 最佳堆范围 | 4GB – 32GB | 32GB - 多 TB | 8GB – 64GB |
| 适用场景 | 通用、批处理、ETL | HFT、实时系统、超大堆 | K8s 微服务、中等堆、内存受限 |
未来演进方向
通过上面的表格可以看出,G1 GC 也面临这其它 GC 给它带来的压力。但是,根据历史 GC 的迭代来看,短时间内 G1 GC 不会很快被 ZGC 等取代。
未来 GC 的演进方向,依旧可能是围绕下面这些场景和需求、特点展开。
- G1 不会被立即取代:它仍是“通用场景”的最优解,JDK 25 的改进使其在 4-32GB 堆范围内极具竞争力
- ZGC 继续蚕食超大堆市场:分代 ZGC(JDK 21+)已解决不分代的吞吐问题,TB 级堆的低延迟场景几乎必选 ZGC
- Shenandoah 的崛起:在 OpenJDK 生态中,Shenandoah 因支持压缩指针(Compressed Oops),内存效率优于 ZGC,适合 K8s 环境
- 下一代 GC 的可能性:Lilliput 项目(压缩对象头)和 Valhalla 项目(值类型)可能彻底改变 GC 的内存模型,届时可能出现全新收集器
总结
G1 GC 的“迟到”本质上是 Java 工程保守主义的胜利。它用了 15 年时间证明自己能在所有场景下至少不劣于 Serial GC。JEP 523 的落地消除了 JVM 行为的一个重大不确定性,即我到底用的是哪个 GC?,但默认不等于最优。
- 如果你的应用运行在
<<4GB 容器且对延迟不敏感,G1 是省心之选 - 如果需要
p999 < 10ms的极致延迟,应显式切换至 ZGC - 如果在
OpenJDK + K8s环境追求低延迟与内存平衡,Shenandoah 值得评估
正如 JEP 523 所言,“禁止未来变更默认 GC”并非其目标,随着应用特征和收集器性能演变,默认 GC 应被重新评估 。G1 的全面默认化,或许只是下一个 GC 时代来临前的“过渡仪式”。

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!