标记-整理算法通过标记存活对象、压缩至内存一端、清理边界外空间三步,消除碎片且不浪费内存;适用于老年代等高存活率场景。

标记-整理算法通过“先标记、再压缩、后清理”三步联动,从根源上消除内存碎片。它不简单丢弃垃圾,而是把存活对象主动归拢到内存一端,腾出整块连续空闲区——这才是应对碎片化的底层逻辑。
标记阶段:精准识别哪些对象必须留下
从 GC Roots(如栈中局部变量、静态字段、JNI 引用等)出发,沿引用链深度遍历,对所有可达对象打上“存活”标记。未被标记的对象即为可回收垃圾。这一步和标记-清除一致,确保回收范围准确无误。
整理阶段:移动存活对象,物理上消除空隙
这是区别于其他算法的核心动作:
- 将所有已标记的存活对象,按顺序紧凑地复制或移动到内存起始端(例如低地址一侧)
- 移动过程中同步更新所有指向这些对象的引用(如栈帧里的变量、其他对象的字段),保证程序逻辑不中断
- 移动完成后,存活对象在内存中连续排列,中间不再夹杂已释放的空洞
清除阶段:一次性释放尾部所有闲置空间
标记和整理完成后,内存呈现“存活区 + 空闲区”的清晰分界:
- 边界之后的所有内存被整体清空,形成一个大而连续的空闲块
- 后续对象分配只需按顺序推进指针(如 bump-the-pointer),无需查找可用碎片
- 彻底规避了因碎片导致的大对象分配失败(如申请 1MB 连续空间却只有多个 200KB 离散空闲块)
为什么它比复制算法更省空间、比标记-清除更抗碎片
标记-整理不像复制算法那样预占一半内存,也不像标记-清除那样放任碎片堆积:
- 它只占用实际所需空间,没有固定的空间浪费
- 压缩过程虽有移动开销,但换来的是长期稳定的连续分配能力
- 特别适配老年代——对象存活率高、不宜频繁复制,又必须避免碎片恶化










