标记-整理算法压缩阶段的核心目标是消除内存碎片,通过三步严格序贯操作实现:先计算存活对象新地址并写入forwarding指针,再更新所有引用指向新地址,最后按新地址移动对象数据。
标记-整理算法的压缩阶段,核心目标是消除内存碎片——它不只回收垃圾,还要把所有存活对象“归拢”到堆内存的一端,腾出一大块连续空闲空间。这个过程不是简单清理,而是涉及对象移动、地址重算和引用更新三重操作。
压缩不是一步到位,而是严格分序执行,避免移动中覆盖或引用错乱:
因为压缩在原堆空间内完成(不依赖额外半区),若先移动对象,而某些引用还指向旧地址,就可能读到被覆盖的脏数据,或导致对象被重复移动。forwarding 指针正是为解耦“定位”与“搬运”而设——它让引用更新有据可依,也使移动可安全延迟。
Lisp2 是最经典的标记-压缩实现,其结构清晰体现上述逻辑:
该算法不要求对象大小一致,适用通用 JVM 堆,但需三次遍历,停顿时间相对较高。
压缩后堆呈现“存活区 + 空闲区”的整齐格局:
所以 CMS 放弃压缩,G1 则采用分区+局部压缩策略来折中。