shenandoah 通过并发疏散、brooks pointer 转发和增量式区域回收实现亚十毫秒级停顿:它用转发指针支持读写隔离,将疏散与引用更新全移至并发阶段,仅需极短 stw 标记,且 region 回收可中断、自适应。

Shenandoah 通过在应用线程运行的同时执行对象疏散(即复制/移动对象),显著降低 GC 停顿时间。它不依赖“Stop-The-World”式暂停来完成核心搬移工作,而是把疏散过程拆解为并发阶段,由专门的 GC 线程与用户线程并行执行。
使用 Brooks Pointer 实现并发读写隔离
Shenandoah 在对象头前插入一个转发指针(Brooks Pointer),让每个对象自带“跳转入口”。当 GC 开始标记后,对象一旦被选中疏散,GC 线程会先在新位置复制对象,再原子更新该指针指向新地址。此后所有对该对象的访问(包括正在运行的应用线程)都会自动通过指针跳转到新副本——无需修改引用字段,也不阻塞读操作。
- 应用线程读取对象时,自动经 Brooks Pointer 转发,看到的是最新副本
- 写操作需配合写屏障:每次写入对象字段前,检查该对象是否已转发,若已转发则更新新位置上的字段
- 避免了传统 CMS 或 G1 中“更新卡表+重新标记”的延迟开销
疏散阶段完全并发执行
Shenandoah 把原本需要 STW 完成的疏散动作(如对象复制、引用更新)全部移到并发阶段。它不等待所有引用被修正完毕才结束 GC 周期,而是允许部分引用仍指向旧位置,靠 Brooks Pointer 动态兜底。
- 疏散由多个并发 GC 工作线程完成,和用户线程共享 CPU 资源
- 引用更新也异步进行:写屏障记录待更新引用,后续由并发线程批量处理
- 只有极短的初始标记和最终标记需要 STW,通常仅几毫秒
回收区域采用增量式、可中断设计
Shenandoah 将堆划分为固定大小的 Region,但不按传统方式“整块回收”,而是按需选择少量 Region 并发疏散。每个 Region 的疏散可随时暂停或迁移,适应不同负载场景。
- 运行时动态决定疏散哪些 Region,优先处理垃圾比例高的区域
- 单次疏散任务粒度小,即使 CPU 暂时紧张也能快速让出资源给应用线程
- 配合自适应的 GC 触发策略(如基于已用内存百分比或分配速率),避免突发停顿
这种设计使 Shenandoah 在大堆(几十 GB 到 TB 级)下仍能稳定维持亚十毫秒级停顿,特别适合低延迟敏感型服务。关键不在“更快地做完”,而在“边跑边做,不打断”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











