你司用上zgc了吗

125 阅读6分钟

ZGC(Z Garbage Collector) 是 Oracle 在 JDK 11 中引入的一种超低延迟垃圾收集器,旨在为大规模应用提供高效的内存管理,尤其是在大内存(几十 GB 到数 TB)场景下。ZGC 的设计目标是将 GC 停顿时间控制在10ms以下,并且在内存规模增长时,GC 停顿时间不会显著增加。

ZGC 的特点

  1. 超低延迟:ZGC 的垃圾回收暂停时间非常短,通常小于 10 毫秒。相比传统垃圾收集器如 CMS 和 G1,它的暂停时间与堆大小无关,因此即便在大内存应用中,ZGC 也能保证很短的 GC 停顿时间。

  2. 高吞吐量:虽然 ZGC 主要以低延迟为目标,但它的吞吐量与其他 GC 如 G1 相比并没有明显劣势。

  3. 大堆支持:ZGC 可以很好地处理 TB 级别的堆内存,是处理大数据、大型应用场景下的理想选择。

  4. 并发标记和压缩:ZGC 几乎所有的工作都是并发执行的,垃圾回收的标记和对象的移动(压缩)都是在不停止应用线程的情况下进行的,这显著减少了对应用程序的影响。

  5. 染色指针(Colored Pointers):ZGC 采用了一种独特的 "染色指针" 技术,将 GC 状态信息编码到对象指针中,以便在对象访问时可以获取 GC 信息。

ZGC 工作流程

ZGC 的垃圾回收过程由四个主要阶段组成:

  1. 并发标记阶段(Concurrent Marking)

    • 这一阶段是并发进行的,ZGC 会标记出所有可达的对象。ZGC 使用一种基于图的遍历算法,依次从 GC Roots 开始,递归遍历对象图,标记所有活动对象。与传统的 GC 不同,ZGC 在标记阶段几乎不会停止应用线程。
  2. 并发预备重定位阶段(Concurrent Prepare for Relocation)

    • 这一阶段,ZGC 通过并发的方式来分析哪些区域需要被压缩(即进行对象的移动)。与其他 GC 不同,ZGC 将标记和压缩分为不同的阶段,因此可以减少停顿时间。
  3. 并发重定位阶段(Concurrent Relocation)

    • 在这个阶段,ZGC 通过 "染色指针" 来支持并发的对象移动。它会在对象被访问时实时更新对象的地址。这样可以确保即使在对象移动期间,程序仍然可以访问这些对象。
  4. 短暂的暂停阶段(Stop-the-World Pause)

    • 尽管 ZGC 几乎所有工作都是并发进行的,但它在整个垃圾收集过程中会有几个非常短暂的停顿。例如,ZGC 会在标记的初始阶段短暂停顿,以处理线程栈中的 GC Roots。另一个停顿是在对象移动之前的同步阶段。

ZGC 的核心技术

1. 染色指针(Colored Pointers)

ZGC 通过给对象的指针(地址)附加 "染色" 信息来追踪对象的状态。染色指针使用对象引用中的一部分位来存储元数据,例如:

  • 对象是否已经被标记。
  • 对象是否已经被压缩。
  • 对象是否正在移动。

染色指针的一个关键好处是,它不需要额外的内存来存储元数据,可以高效地处理对象状态信息。

2. Load barriers(加载屏障)

ZGC 使用了一种叫做 "加载屏障" 的技术。加载屏障是一种轻量级机制,作用是在每次读取对象引用时,都会进行一次轻量级检查,确保该引用指向的是最新的地址,并根据需要更新对象引用。这使得 ZGC 可以在垃圾收集期间安全地移动对象,而不影响正在运行的应用。

3. 并发标记和压缩

ZGC 的标记和对象移动(压缩)是并发进行的。这意味着,即使在进行垃圾回收的过程中,应用程序也可以继续运行,而不会因为垃圾收集暂停而中断。传统的垃圾收集器通常会在标记和压缩过程中 "Stop-the-World",而 ZGC 的并发模型则极大地减少了停顿时间。

ZGC 与其他 GC 的对比

特性ZGCG1 GCCMS GCParallel GC
主要目标低延迟低延迟,适中吞吐量低延迟高吞吐量
最大堆大小TB 级别一般几百 GB一般几百 GB一般几百 GB
暂停时间< 10ms,且与堆大小无关短暂停时间,随着堆增长而增加停顿较短,但可能出现 "浮动垃圾"停顿时间长
对象压缩并发混合模式无压缩Stop-the-World 压缩
染色指针

使用 ZGC 的场景

ZGC 适用于以下场景:

  1. 超大堆内存应用:在内存需求达到几十 GB 到数 TB 级别的应用中,ZGC 能够提供低停顿的垃圾回收体验。
  2. 低延迟应用:对于金融系统、实时响应系统、大规模在线服务等对延迟非常敏感的场景,ZGC 的短暂停顿特性非常适合。
  3. 混合负载:ZGC 适合在有大数据处理、批量计算与交互式任务混合的负载中使用。

如何使用 ZGC

在启动 Java 应用时,可以通过以下 JVM 参数启用 ZGC:

java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xmx<size> -Xms<size> -jar yourapp.jar
  • -XX:+UnlockExperimentalVMOptions:启用实验性 VM 选项(ZGC 是实验性特性,需显式启用)。
  • -XX:+UseZGC:启用 ZGC 作为垃圾回收器。
  • -Xmx-Xms:分别设置最大和最小堆内存大小。

ZGC 的优缺点

优点:

  • 低延迟:堆内存再大,ZGC 都可以保持极短的 GC 停顿时间,通常小于 10 毫秒。
  • 并发标记与压缩:所有标记和压缩操作几乎都是并发进行,减少了 Stop-the-World 的时间。
  • 大堆支持:ZGC 支持 TB 级别的大堆,在大数据处理场景中非常适用。

缺点:

  • 实验性:尽管 ZGC 从 JDK 11 开始引入,但它仍然是一种实验性特性,在某些特殊场景下可能存在未被充分测试的行为。
  • 吞吐量:尽管 ZGC 能保证极低的延迟,但与 Parallel GC 等主要关注吞吐量的收集器相比,吞吐量稍低,尤其是在某些极端负载下。
  • 32位系统不支持:ZGC 仅支持 64 位系统,特别是 Linux、macOS 和 Windows 的 64 位版本。

总结

ZGC 是一种极具创新性的垃圾回收器,特别适合对延迟要求极高或堆内存极大的应用场景。通过其独特的染色指针和加载屏障机制,ZGC 实现了低停顿、并发标记和并发压缩的功能,保证了应用的实时性和高效性。

对于需要处理超大内存且对延迟敏感的 Java 应用程序,ZGC 提供了优异的垃圾回收解决方案。