shenandoah的核心目标是通过全堆并发整理主动消除内存碎片。它采用标记-整理算法,借助brooks指针和读屏障实现对象迁移与引用更新的全程并发,无需stw即可完成紧凑化,确保region级无碎片且整理效果与堆大小无关。

Shenandoah 的核心目标之一,就是解决传统 GC(如 CMS)遗留的内存碎片问题——它不靠“回避碎片”,而是通过**全堆并发整理**主动消除外部碎片。
为什么老式回收器留碎片?
像 CMS 这类标记-清除回收器,只清理死亡对象、不移动存活对象。结果是:堆里空出大量零散小块,但大对象申请时找不到连续空间,最终触发 Full GC 甚至 OOM。Shenandoah 明确拒绝这种“治标不治本”的做法。
Shenandoah 怎么边运行边整理?
它采用标记-整理(Mark-Compact)算法,但关键在于:整理不是 STW 阶段集中完成的,而是在用户线程持续运行时,并发执行对象迁移与引用更新:
- 并发回收阶段(Concurrent Evacuation):选定待回收的 Region(即回收集),将其中存活对象复制到其他空闲 Region;原 Region 整块腾空,天然无碎片。
- 转发指针(Brooks Pointer)机制:每个对象头额外增加一个 8 字节指针,初始指向自己;迁移后指向新地址。所有对该对象的读访问都经由读屏障检查并自动重定向,无需暂停应用线程。
- 并发引用更新(Concurrent Update Reference):在对象迁移完成后,异步扫描并修正堆中所有旧引用,这个过程也基本并发进行,仅需极短的初始同步点。
整理效果与适用场景
每次回收周期结束后,被处理过的 Region 都是完全干净、连续可用的。长期运行下,整个堆能维持高度紧凑状态:
- 支持大对象直接分配,不再因碎片导致晋升失败或频繁退化为 Full GC;
- 适用于堆大小从几 GB 到上百 GB 的场景,碎片控制能力与堆容量无关;
- 特别适合对延迟敏感、且对象生命周期分布不均的应用,比如实时风控、高频交易网关。
和 G1/ZGC 的整理差异
虽然 G1 和 ZGC 也具备整理能力,但路径不同:
- G1 是混合回收:仅在老年代部分 Region 触发整理,属于“选择性压缩”,碎片可能在未回收区域残留;
- ZGC 使用染色指针 + 并发转移,在指针位中编码状态,对象移动更轻量,但依赖硬件支持(如 64 位地址空间富余位);
- Shenandoah 不依赖特殊硬件,靠对象头转发指针实现,兼容性更广,但每个对象多占 8 字节内存。











