# 44. ZGC 如何做到低延迟?它适用于哪些业务场景?

# 标准答案

ZGC(Z Garbage Collector)通过染色指针(Colored Pointers)+ 读屏障(Load Barrier)+ 并发回收等技术实现低延迟,确保 STW(Stop-The-World)时间通常小于 1ms。它适用于低延迟、高吞吐的业务场景,如金融交易、高并发 Web 服务器、游戏服务器和 AI 计算等。

# 答案解析

ZGC 的低延迟特性主要依赖于以下关键技术:

# 1. 染色指针(Colored Pointers)

传统 GC 需要在外部维护对象的标记状态,而 ZGC 直接在 64 位指针的高位存储对象的 GC 状态,如:

  • Marked0 / Marked1:标记阶段使用
  • Remapped:表示对象是否被转移
  • Finalizable:标记需要 finalize 的对象
    这种方式减少了额外的元数据开销,提高了并发回收的效率。

# 2. 读屏障(Load Barrier)

ZGC 采用 读屏障(Load Barrier) 来拦截对象访问,当访问对象时,ZGC 检测对象是否已移动,并在访问时完成对象转移,从而避免 GC 过程中集中 STW。
这与 G1 的**写屏障(Write Barrier)**不同,G1 依赖写屏障来维护 Remembered Set,而 ZGC 主要在对象读取时进行操作,实现更高的并发性。

# 3. 完全并发回收

传统 GC 在对象移动时必须暂停应用线程,而 ZGC 允许大部分 GC 任务并发执行,仅在以下阶段发生 STW:

  • 初始标记(STW,通常 <1ms):标记 GC Roots。
  • 并发标记(应用线程正常运行)。
  • 并发预备重分配(Relocation):确定需要移动的对象。
  • 并发对象转移(与应用线程一起执行)。
  • STW 更新引用(<1ms):确保所有指针指向最新对象。

这种回收方式避免了 Full GC 造成的长时间停顿,使得 STW 时间极短(<1ms)。

# 4. 无分代设计(Region-less)

传统 GC(如 G1、CMS)采用分代回收(年轻代 + 老年代),但 ZGC 采用无分代设计,所有对象均在相同的堆区域进行回收,避免了跨代晋升带来的额外开销,减少了 GC 停顿时间。

# 5. 大堆支持(最高 16TB)

由于染色指针技术,ZGC 可以支持 16TB 的超大堆空间,而 G1 受限于 57GB(压缩指针模式)。这使得 ZGC 适用于大数据、AI 计算等超大内存场景。

# ZGC 适用的业务场景

ZGC 主要适用于对 低延迟、超大内存 有严格要求的业务,包括:

  1. 金融交易系统:如股票撮合、外汇交易,要求毫秒级响应,ZGC 的低 STW 可减少交易延迟。
  2. 高并发 Web 服务器:如电商、社交媒体,ZGC 确保请求处理不中断,降低 P99 响应时间。
  3. 游戏服务器:游戏对帧率要求严格,GC 停顿会造成卡顿,ZGC 可提供更流畅的体验。
  4. AI 和大数据计算:AI 训练通常需要大内存(TB 级),ZGC 通过支持 16TB 堆避免频繁 GC 影响计算效率。

# 深入追问

  1. 为什么 ZGC 采用读屏障而不是写屏障?

    • 读屏障允许在访问对象时完成对象转移,而写屏障通常需要在对象更新时维护元数据,读屏障的方式更适合并发 GC。
  2. ZGC 是否适用于所有 Java 应用?

    • ZGC 适用于低延迟、大堆应用,但由于 GC 线程会占用 CPU 资源,对于 CPU 密集型应用(如高频计算)可能不是最佳选择。
  3. G1 和 ZGC 在 STW 上的根本区别?

    • G1 仍然需要在 Root Scanning 和 Mixed GC 期间进行 STW,而 ZGC 的 STW 仅限于极短的标记阶段(通常 <1ms)。

# 相关面试题

  • G1、ZGC、Shenandoah 在低延迟场景下的对比?
  • 染色指针(Colored Pointers)如何优化 GC?
  • 如何选择合适的 GC?不同 GC 的适用场景是什么?