标记-整理算法的核心价值在于以一次可控移动开销换取长期零碎片与高内存利用率:它不预占空间、不丢弃可用内存,通过标记存活对象、将其紧凑迁移至内存一端并更新引用,最终清空边界外区域,形成连续空闲块,特别适配老年代高存活率场景。

标记-整理算法的核心价值,就在于它用一次可控的移动开销,换来了长期稳定的高内存利用率和零碎片状态。
内存利用率为什么高
它不预占额外空间,也不丢弃可用内存——所有存活对象被紧凑排列,剩余空间全部连成一块。相比复制算法固定浪费一半堆空间,也比标记-清除留下大量离散空洞,标记-整理实际只占用对象真实所需的空间。
- 没有“预留区”:不像新生代复制算法要求 From/To 区始终有一半空闲
- 无闲置缝隙:整理后存活区与空闲区严格分界,空闲部分100%连续可用
- 支持大对象分配:比如需要 512KB 连续内存时,只要总空闲 ≥ 512KB 就能成功,不会因碎片而失败
碎片整理是怎么实现的
不是靠“清理碎块”,而是让存活对象自己“归队”——把它们物理迁移到内存一端,腾出另一端整片空白。
- 先标记:从 GC Roots(如栈变量、静态字段)出发,遍历引用链,标出所有必须保留的对象
- 再整理:按地址顺序,把已标记对象逐个搬运到起始端(例如低地址),过程中保持相对顺序
- 同步更新:所有指向这些对象的引用(栈中变量、其他对象字段)都重定向到新地址,程序逻辑不受影响
- 最后清界:以最后一个存活对象为界,边界之后所有内存一次性释放,形成单一大块空闲区
为什么特别适合老年代
老年代对象存活率高、生命周期长,频繁复制代价太大,而放任碎片又会快速导致分配失败。标记-整理在两者间取得平衡:
- 移动成本虽存在,但远低于全堆复制;相比标记-清除,它避免了碎片持续恶化
- 一次整理可支撑多次分配,尤其利于长期运行服务中大对象(如缓存、长连接缓冲区)的稳定申请
- G1、ZGC 等现代回收器虽不直接用经典标记-整理,但其 Region 内的局部压缩、记忆集维护等机制,本质延续了这一思想
它不追求单次最快,而是以空间连续性保障系统长期吞吐与稳定性。











