Shenandoah 收集器之低延迟回收原理

作者:袖梨 2026-07-08
Shenandoah实现低延迟的核心在于将标记、清理、回收等GC工作全程并发执行,仅初始与最终标记需毫秒级STW;通过连接矩阵替代记忆集、Brooks指针加读屏障解决并发移动难题,并默认不分代以简化逻辑。

Shenandoah 实现低延迟的核心,在于把绝大部分 GC 工作移到与用户线程并发执行,大幅压缩“Stop-The-World”(STW)时间,且停顿长短基本不随堆大小或存活对象数量增长。

并发标记与回收全程并行

它将传统上必须暂停应用才能完成的标记、清理、对象移动等步骤,全部设计为可并发运行。例如:

  • 初始标记和最终标记阶段仍需短暂 STW,但只扫描 GC Roots 或处理少量残留引用,耗时固定,通常在毫秒级;
  • 并发标记遍历对象图、并发清理空 Region、并发回收(即复制存活对象)全部与业务线程同时进行;
  • 哪怕堆从几 GB 扩到上百 GB,只要 GC Roots 数量不变,初始标记停顿就几乎不变。

用连接矩阵替代记忆集

G1 为追踪跨 Region 引用,需维护开销高昂的记忆集(Remembered Set),内存和 CPU 消耗随 Region 数量增长。Shenandoah 改用“连接矩阵”——一张二维布尔表,RegionN → RegionM 有引用就在 (N,M) 格打标。这种全局结构:

  • 避免按 Region 单独计算和更新记忆集;
  • 显著降低写屏障负担和内存占用;
  • 减少伪共享,提升多核缓存效率。

Brooks 指针 + 读屏障解决并发移动难题

对象在被复制过程中,用户线程可能仍在访问旧地址。Shenandoah 在每个对象头前插入一个转发指针(Brooks Pointer),并通过读屏障拦截所有对象读取操作:

  • 若发现对象已被移动,读屏障自动重定向到新地址;
  • 若尚未移动,照常读取并触发懒迁移;
  • 这样既保证一致性,又无需全局暂停修正所有引用。

默认不分代,简化回收逻辑

它不区分新生代/老年代 Region,所有 Region 统一评估回收价值。这带来两个直接好处:

  • 省去分代间引用扫描的复杂性(如卡表维护、跨代记忆集更新);
  • 避免因分代假设失准导致的冗余扫描或漏标;
  • 让回收决策更聚焦于实际内存压力,响应更直接。

相关文章

精彩推荐