标记-整理算法适合老年代回收,因其能消除内存碎片、充分利用空间,且仅移动存活对象,相比复制算法避免双倍内存开销,相比标记-清除算法解决碎片导致的大对象分配失败问题。

标记-整理算法适合老年代回收,核心在于它能兼顾老年代对象“存活率高、数量多、移动成本需可控”的特点,避免复制算法的巨额开销,又解决标记-清除算法的碎片问题。
老年代对象的典型特征
老年代中存放的是经过多次 Minor GC 仍存活的对象,比如 Spring Bean、缓存实例、连接池、全局配置等。它们有三个关键特征:
- 存活时间长:多数对象在老年代中可存在整个应用生命周期
- 存活比例高:通常 80%–95% 的老年代对象是活跃的,只有少量真正可回收
- 对象体积偏大且分布不均:容易因内存碎片导致大对象分配失败
为什么复制算法不适用于老年代
复制算法要求把所有存活对象从一块空间复制到另一块空闲空间。但在老年代中:
- 每次要复制大量存活对象,CPU 和内存带宽开销巨大
- 需要预留同等大小的备用空间,堆内存利用率直接砍半,不经济
- 无法应对对象大小差异大的场景(如一个 2MB 的缓存对象 + 几百个 1KB 的辅助对象)
标记-整理如何精准匹配老年代需求
它分两步执行:先标记所有存活对象,再将它们统一向内存起始端紧凑排列,最后清理边界外的连续空白区域。
- 不浪费空间:无需双倍内存,全部利用现有老年代空间
- 消除碎片:整理后内存连续,保障后续大对象(如大数组、批量响应体)可顺利分配
- 开销相对可控:虽然移动对象有成本,但只移动存活对象,且现代 JVM 会优化移动逻辑(如按页批量处理、使用卡表减少扫描范围)
对比标记-清除:为何整理比清除更可靠
标记-清除虽省去移动步骤,但遗留大量不连续空闲块。在老年代中,这极易引发两种问题:
- 分配大对象时触发不必要的 Full GC,即使总空闲内存充足
- 长期运行后碎片累积,GC 效率持续下降,甚至出现“Concurrent Mode Failure”等严重告警
标记-整理用一次可控的整理代价,换来长期稳定的分配效率和更低的 GC 频次,对服务类应用尤为关键。











