Skip to content

新型回收器(Epsilon/Shenandoah/ZGC)

新一代 GC 的崛起

JDK 11 之后,JVM 引入了三个革命性的垃圾回收器:EpsilonShenandoahZGC。它们的共同特点是超低停顿,解决了传统 GC 无法解决的长停顿问题。

Epsilon GC:不做任何回收

Epsilon 是什么

Epsilon 是「无操作 GC」——它分配内存,但不回收任何垃圾。当内存耗尽时,直接 OOM。

bash
# 启用 Epsilon GC
java -XX:+UseEpsilonGC MyApp

使用场景

Epsilon 只适合特定场景:

场景说明
极短生命周期的程序程序运行时间比 GC 停顿时间还短
测试内存分配器用于测试其他内存管理机制
内存足够且不产生垃圾嵌入式、实时系统
性能基准测试排除 GC 干扰的基准测试

Epsilon 的特点

特点说明
零停顿不进行任何垃圾回收,无 STW
无内存回收分配直到 OOM
分配器效率高无任何 GC 开销
仅分配适合不需要 GC 的场景

Epsilon 的配置

bash
# Epsilon + 最大堆
java -Xmx2g -XX:+UseEpsilonGC MyApp

# 注意:Epsilon 不处理垃圾,所以不要设置过小的堆

Shenandoah GC:转发指针实现并发压缩

Shenandoah 是什么

Shenandoah 是 JDK 12 引入的低延迟 GC,核心目标是极短的停顿时间

bash
# JDK 12+ 启用 Shenandoah
java -XX:+UseShenandoahGC MyApp

转发指针(Brooks Pointer)

Shenandoah 的核心技术是转发指针(Brooks Pointer)

传统 GC 的对象引用:
  引用 ──→ 对象 A

Shenandoah 的对象引用:
  引用 ──→ 对象 A(副本)──→ 原始对象 A


          转发指针(Brooks Pointer)

对象移动后:
  引用 ──→ 对象 A(副本)───修改转发指针──→ 原始对象 A(已移动)


          引用不变,只需修改转发指针

转发指针的原理

当 Shenandoah 需要压缩堆时:

压缩前:                    压缩后:
┌─────────────┐          ┌─────────────┐
│ Region A     │          │ Region A     │
│  引用 ──→ [A]│          │  引用 ──→ [A]  ──修改──→ (A 已移动)
└─────────────┘          └─────────────┘


                        ┌─────────────┐
                        │ Region B     │
                        │      [A]     │
                        └─────────────┘

引用不需要改变,只需要修改 A 的转发指针
→ GC 可以在并发时压缩,不需要 STW

读屏障

Shenandoah 使用读屏障(Load Barrier)来维护转发指针的一致性:

java
// 读屏障的工作:
Object obj = ref.get();  // 读取引用
// 隐式地,JVM 检查 obj 的转发指针是否有效
// 如果对象被移动了,更新到新位置

读屏障的开销很小(约 5%~10%),但换来了极短的停顿时间

Shenandoah vs G1

维度ShenandoahG1
停顿时间< 10ms(并发压缩)数十毫秒
压缩方式并发压缩(不 STW)STW 时压缩
堆大小影响几乎不受影响堆越大停顿越长
JDK 版本12+(JDK 15 红帽移出 OpenJDK)7+(JDK 9 默认)
算法转发指针 + 读屏障SATB + Region

ZGC:着色指针实现亚毫秒停顿

ZGC 是什么

ZGC(Z Garbage Collector) 是 JDK 11 引入、JDK 15 生产就绪、JDK 21 成为默认的超低延迟 GC

bash
# JDK 11~14:启用 ZGC
java -XX:+UseZGC MyApp

# JDK 15+:默认 ZGC 已经可用
# JDK 21+:ZGC 成为默认 GC

着色指针(Colored Pointers)

ZGC 使用 着色指针(Colored Pointers) 技术,把 GC 信息编码到对象的引用中:

64 位引用 → 64 位地址空间中,ZGC 只使用低 42 位作为地址
                    高位存储 GC 元数据:

┌──────────┬──────────┬──────────────────────┐
│ 44~46    │   47    │     0~44              │
│ (GC状态)  │ (大堆标志)│     (实际地址)         │
└──────────┴──────────┴──────────────────────┘

ZGC 使用 3 个 GC 位存储对象的状态:

含义
Marked0/Marked1对象存活(用于并发标记)
Remapped引用已更新(对象已移动)

ZGC 的工作过程

ZGC 完全在颜色指针的帮助下,实现了几乎所有阶段的并发

ZGC 阶段:

1. 初始标记 ── STW(短暂)─── 标记 GC Roots 直接引用的对象

2. 并发标记 ── 并发 ────────── 标记所有存活对象(着色指针)

3. 再标记 ── STW(极短)─────── 修正着色指针

4. 并发准备 ── 并发 ────────── 计算回收价值

5. 并发回收 ── 并发 ────────── 移动存活对象,更新引用

6. 并发重映射 ── 并发 ──────── 更新所有引用

ZGC 的优势

优势说明
停顿时间固定不超过 1ms,与堆大小无关
吞吐量损失小约 10%~15% 吞吐量损失
堆大小无关支持从 MB 到 TB 的堆
并发压缩对象移动时不需要 STW
彩色指针不需要 Card Table/RSet

ZGC 的局限性

局限性说明
吞吐量不如 Parallel GC(高吞吐)
不支持类卸载JDK 15+ 已支持
堆大小 < 16MB需要对 44 位地址空间利用
暂不支持 JDK 8需要 JDK 11+

ZGC 的参数

bash
# 基本使用
java -XX:+UseZGC -Xms16g -Xmx16g MyApp

# 设置停顿时间目标(软目标)
java -XX:+UseZGC -XX:MaxGCPauseMillis=1ms MyApp

# 设置并发 GC 线程数
java -XX:+UseZGC -XX:ConcGCThreads=8 MyApp

三种新型 GC 的对比

维度EpsilonShenandoahZGC
停顿时间0(无 GC)< 10ms< 1ms
吞吐量最高
堆大小任意任意任意(最大 TB 级)
并发部分并发完全并发
压缩并发压缩并发压缩
JDK 版本11+12+(OpenJDK)11+(15+生产就绪)
JDK 2121+不在 OpenJDK默认 GC

选型建议

场景推荐 GC原因
超低延迟(< 1ms)ZGC亚毫秒停顿
低延迟(< 10ms)ZGC / G1ZGC 更稳定
高吞吐量批处理Parallel GC吞吐量优先
无垃圾程序Epsilon不做 GC
JDK 8 升级G1JDK 9+
TB 级大堆ZGC支持超大堆

本节小结

三种新型 GC 的核心特点:

GC核心技术停顿时间吞吐量
Epsilon无操作0最高
Shenandoah转发指针 + 读屏障< 10ms
ZGC着色指针< 1ms

ZGC 是现代 JVM GC 的巅峰——它解决了 GC 停顿时间与堆大小无关的问题,是 JDK 21 的默认 GC。

下一节,我们来看 7 种回收器总结与调优建议

基于 VitePress 构建