标记整理算法通过“移动+压缩”消除老年代外部碎片:先标记存活对象,再将其紧凑移至内存一端,清空边界后空间,无需预留区域、适合高存活率场景,大对象分配更可靠,但需STW并承担拷贝与引用更新开销。

标记整理算法通过“移动+压缩”两个核心动作,直接从物理层面消除老年代的外部碎片。
存活对象统一向一端滑动
它不像标记-清除那样只释放空间、留下空洞,也不像复制算法那样依赖额外空闲区域。而是先标记所有存活对象,再将它们全部紧凑地挪到内存起始端(比如低地址方向),中间不留空隙。挪完后,把边界之后的所有内存一次性清空。这样整个老年代就变成一块连续可用的大空间。
不依赖预留空间,适合高存活率场景
老年代对象存活率常达80%以上,复制算法要预留等量空闲区,代价太高。标记整理不需要另一半空间,只在原区域内部重排,空间利用率接近100%。例如4GB老年代,即使90%对象存活,也能完整利用这4GB,不会因“没地方搬”而失败。
整理后的大对象分配不再受阻
外部碎片消失意味着:只要总空闲空间 ≥ 请求大小,就一定能分配成功。比如整理后腾出连续512KB,此时申请一个500KB的byte[]数组就不会触发promotion failed或concurrent mode failure——这是CMS等仅标记清除的收集器最常遇到的瓶颈。
注意:整理本身有开销
对象移动会带来三类成本:一是拷贝内存数据的物理开销;二是所有指向这些对象的引用必须同步更新(指针修正);三是整个过程需暂停应用线程(Stop-The-World)。所以它虽治标又治本,但停顿时间比标记-清除长,这也是G1、ZGC等现代收集器改用局部整理或并发整理的原因。


















