标记-整理算法因避免内存碎片且无需预留50%空间,特别适合老年代高存活率场景;它通过三步整理保障引用一致、支持大对象分配,并与分代机制协同优化GC压力。

标记-整理算法在复杂业务场景中之所以表现稳健,核心在于它既避免了内存碎片,又不需要像复制算法那样牺牲一半空间——这对长期运行、对象存活率高、内存压力大的系统尤为关键。
适合老年代的稳定回收策略
复杂业务(如金融交易、订单履约、实时风控)中,大量对象会经历多次GC后晋升到老年代,且长期存活。此时若用标记-清除,碎片会快速累积,导致大对象分配失败、频繁触发Full GC;而复制算法因存活率高、复制开销大,在老年代完全不适用。标记-整理则天然适配:
- 只移动存活对象,按地址顺序紧凑排列,释放连续空闲空间
- 无需额外预留50%内存,空间利用率接近100%
- 虽有STW(Stop-The-World),但停顿时间相对可控,尤其在G1、ZGC等现代回收器中已大幅优化整理逻辑
应对高存活率与大对象混合场景
电商大促期间,缓存对象、聚合订单、用户会话等常驻内存,同时伴随临时报表、日志切片等短生命周期对象。这种混合负载下:
- 标记阶段仍基于根可达性分析,准确识别真正存活的对象
- 整理阶段通过“计算新位置→更新所有引用→实际移动”三步完成,确保引用一致性
- 对大对象(如图片缓存、序列化数据)友好——不会因碎片无法分配,也避免了复制时的巨额内存拷贝
与分代机制协同降低整体GC压力
标记-整理并非孤立使用,而是嵌入分代收集框架中发挥最大价值:
立即学习“Java免费学习笔记(深入)”;
- 新生代继续采用复制算法(Eden + Survivor),高效清理朝生夕灭对象
- 老年代默认或显式启用标记-整理(如Serial Old、Parallel Old),承接长期对象
- G1回收器将堆划分为Region,对回收价值高的Region内部执行类似标记-整理的“局部压缩”,兼顾吞吐与延迟
调优时需关注的关键点
要让标记-整理在复杂业务中真正“稳健”,不能只依赖算法本身,还需配合合理配置:
- 避免堆过小导致老年代频繁触发——增大-Xmx并保持-Xms与-Xmx一致,减少动态扩容带来的额外整理压力
- 监控Full GC频率与耗时:若单次整理耗时突增,可能是对象引用关系过于复杂(如深度嵌套、循环引用未及时断开)
- 慎用System.gc():强制触发标记-整理会打断业务线程,尤其在高并发写入场景下易引发雪崩
- 结合ZGC或Shenandoah等低延迟回收器时,其“并发整理”能力可进一步削弱STW影响,更适合毫秒级SLA要求的系统


















