标记-整理算法通过移动存活对象至内存一端并更新引用,消除老年代内存碎片,确保大对象可分配连续空间;其代价是复制与引用修正开销,故适用于gc频率低但需高内存连续性的老年代场景。

标记-整理算法在老年代避免内存碎片,核心在于“移动”——它不只清理垃圾,还把所有存活对象集中搬到内存一端,腾出连续的空闲空间。
标记阶段:先确定哪些对象要留下
从 GC Roots(如栈中局部变量、静态字段、常量池引用等)出发,遍历所有可达对象并打上标记。未被标记的对象即为垃圾,后续会被回收。
整理阶段:把存活对象“归拢”到一起
与标记-清除不同,标记-整理不会原地清除,而是将所有已标记的存活对象按顺序向内存起始端(或末端)紧凑排列:
- 对象移动后,它们之间的地址是连续的,中间不留空隙
- 移动过程会更新所有指向这些对象的引用(比如栈里、其他对象字段中的地址),确保程序逻辑不受影响
- 整理完成后,只需将“边界”之后的所有内存一次性清空,得到一大块连续空闲空间
为什么这对老年代特别重要
老年代对象存活率高、生命周期长,长期运行后容易因多次不规则回收产生大量小块碎片。大对象(如大数组、缓存块)申请时需要连续内存,碎片会导致即使总空闲空间足够也无法分配——标记-整理直接消除这种风险。
代价与适用性
整理需要复制对象并修正引用,比单纯清除更耗时,所以它适合老年代这种 GC 频率低、但对内存连续性要求高的场景。现代 JVM(如 Serial Old、Parallel Old、G1 的部分 Mixed GC)在老年代回收中会启用该策略,ZGC 和 Shenandoah 则通过读屏障和并发移动进一步降低停顿。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











