以下是关于 CMSG1ZGC 三种垃圾回收器的详细对比分析,涵盖适用场景、优势、劣势等方面。


一、CMS(Concurrent Mark-Sweep)垃圾回收器

1️⃣ 工作机制
  • 初始标记 :标记 GC Roots,短暂停顿。
  • 并发标记 :遍历对象图,标记可达对象。
  • 重新标记 :修复并发标记期间发生的对象引用变化(短暂停顿)。
  • 并发清理 :清理垃圾对象。
  • 并发重置 :重置本次GC过程中的标记数据。
2️⃣ 优点
  • 低延迟 :非常适合需要低延迟的应用场景,例如响应时间敏感的交互式应用。
  • 并发收集 :并发标记和并发清理阶段可以和业务线程同时运行,减少停顿时间。
3️⃣ 缺点
  • 内存碎片 :清理过程中不整理内存,容易导致内存碎片问题,可能引发 Full GC
  • 单线程清理 :并发清理阶段可能效率较低。
  • 高 CPU 开销 :需要与业务线程抢占 CPU 资源。
  • 浮动垃圾 :无法处理浮动垃圾(在并发标记和并发清理阶段又产生垃圾,这种浮动垃圾只能等到下一次gc再清理了)
  • 回收滞后触发Full GC停顿 :执行过程过程中的不确定性,会存上上一次垃圾回收还没执行完,然后垃圾回收又被触发的情况,特别是在并发标记和并发清理阶段会出现,一边回收,系统一边运行,也许没回收完就再次触发full gc,也就是"concurrent model failure",此时会进入stop the world,用serial old垃圾收集器来回收
4️⃣ 适用场景
  • 适用于低延迟需求的应用,例如 Web 服务、交易系统。

二、G1(Garbage-First)垃圾回收器

1️⃣ 工作机制
  • 基于分区(Region)的回收策略,分区大小可调(通常 1MB~32MB)。
  • G1 主要通过:
  • 初始标记 :标记 GC Roots,可达对象。
  • 并发标记 :扫描整个堆,标记可回收对象。
  • 最终标记 :修复并发标记期间发生的对象变化。
  • 筛选回收 :根据分区的垃圾比例优先回收高收益区域。
2️⃣ 优点
  • 并行与并发 :G1能充分利用CPU、多核环境下的硬件优势,使用多个CPU(CPU或者核心)来缩短Stop-The-World停顿时间。部分其他收集器需要停顿Java线程来执行GC动作,G1收集器仍然可以通过并发的方式让java程序继续执行
  • 分代收集:虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但还是保留了分代的概念。
  • 空间整合:与CMS的“标记-整理”算法不同,G1从整体来看是基于“标记整理”算法算法实现的收集器;从局部上来来看是基于"标记整理"算法来实现的收集器;从局部上来看是基于“复制”算法实现的。
  • 可预测停顿时间 :可以通过 -XX:MaxGCPauseMillis 设置目标停顿时间。
  • 高吞吐量 :分区化管理内存,提高内存利用率。
3️⃣ 缺点
  • 配置复杂 :需要较多的调优工作以达到最佳性能。
  • 吞吐量略低 :相比 Parallel GC,在高吞吐量场景稍逊。
4️⃣ 适用场景
  • 内存管理复杂且需要低延迟的场景,例如实时分析系统、大型 Java 应用。
  • 50%以上的堆被存活对象占用
  • 对象分配和晋升的速度变化非常大
  • 垃圾回收时间特别长,超过1秒
  • 8GB以上的堆内存(建议值)
  • 停顿时间是500ms以内

三、ZGC(Z Garbage Collector)

1️⃣ 工作机制
  • 基于Region内存布局
  • 暂时不分代
  • 低延迟 为目标,设计为 完全并发 的垃圾回收器。
  • 支持超大堆(最高 16TB),采用 读屏障颜色指针技术来实现可并发的标记-整理算法。
  • ZGC通过:
  • 并发标记:与G1一样,并发标记是遍历对象图做可达性分析的阶段,它的初始标记(Mark Start)和最终标记(Mark End)也会出现短暂的停顿,与G1不同的是,ZGC的标记是在指针上而不是在对象上进行的,标记阶段会更新颜色指针中的Marked 0、Marked 1标记位。
  • 并发预备重分配:这个阶段要根据特定的查询条件统计得出本次收集过程要清理哪些Region,将这些Region组成重分配集(Relocation Set)。ZGC每次回收都会扫描所有的Region,用范围更大的扫描成本换取省去G1中记忆集的维护成本。
  • 并发重分配:重分配是ZGC执行过程中的核心阶段,这个过程要把重分配的存活对象复制到新的Region上,并为重分配集中的每个Region维护一个转发表(Forward Table),记录从旧对象到新对象的转向关系。ZGC收集器能仅从引用上就明确得知一个对象是否处于重分配集之中,如果用户线程并发访问了位于重分配集中的对象,这次访问将会被预置的内存屏障(读屏障)所截获,然后立即根据Region上转发表记录将访问转发到新复制的对象上,并同时修正更新该引用的值,使其直接指向新对象,ZGC将这种行为称为指针的治愈(Self-Healing)能力。
  • 并发重映射:重映射所做的就是修正整个堆中指向重分配集中旧对象的所有引用,但是ZGC中对象引用存在“自愈”功能,所以这个重映射操作并不很迫切。ZGC很巧妙地把并发重映射阶段要做的工作,合并到下一次垃圾收集循环中的并发标记阶段里去完成,反正它们都是要遍历所有对象的,这样合并就节省了一次遍历对象图的开销。一旦所有指针都被修正之后,原来记录新旧对象关系的转发表就可以释放掉了。
2️⃣ 优点
  • 极低停顿时间 :单次停顿通常不超过 10ms。
  • 大堆支持 :针对超大内存的应用进行了优化。
  • 无内存碎片 :通过并发整理内存,保持内存连续性。
3️⃣ 缺点
  • 相对较高的 CPU 开销 :需要额外的 CPU 资源处理读屏障。
  • 浮动垃圾
  • 新生代管理能力稍弱 :相比 G1,处理短生命周期对象略显不足。
  • 较高的 JVM 版本要求 :需要 Java 11+。
4️⃣ 适用场景
  • 超大堆应用(如 8GB+ 内存)。
  • 低延迟要求非常高的场景,例如金融交易系统、在线游戏。

四、对比总结

特性

CMS

G1

ZGC

目标

降低延迟

平衡延迟与吞吐量

极低延迟

停顿时间

较低,但存在 Full GC 风险

可控停顿时间(可调)

极低(<10ms)

内存管理

无内存整理,易碎片化

分区压缩,碎片较少

并发整理,无碎片

吞吐量


较高

较低

适用场景

低延迟的中小型应用

内存利用率优化的大型应用

超大堆低延迟应用

支持 JVM

Java 8+

Java 9+

Java 11+