最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
标记-整理算法的压缩阶段原理及其实现
时间:2026-07-13 09:01:46 编辑:袖梨 来源:一聚教程网
标记-整理算法压缩阶段的核心目标是消除内存碎片,通过三步严格序贯操作实现:先计算存活对象新地址并写入forwarding指针,再更新所有引用指向新地址,最后按新地址移动对象数据。
标记-整理算法的压缩阶段,核心目标是消除内存碎片——它不只回收垃圾,还要把所有存活对象“归拢”到堆内存的一端,腾出一大块连续空闲空间。这个过程不是简单清理,而是涉及对象移动、地址重算和引用更新三重操作。
压缩阶段的关键步骤
压缩不是一步到位,而是严格分序执行,避免移动中覆盖或引用错乱:
- 计算新位置:遍历整个堆,对每个已标记的存活对象,按顺序分配紧邻的新地址(通常从堆底开始),并将其写入对象头的 forwarding 指针中;
- 更新所有引用:扫描全局(包括栈、寄存器、其他对象字段等),将所有指向原地址的引用,替换成 forwarding 指针所记录的新地址;
- 实际移动对象:最后才按新地址顺序,把对象数据逐个复制过去——此时因引用已全部更新,不会出现“边搬边用”的冲突。
为什么必须先更新引用再移动?
因为压缩在原堆空间内完成(不依赖额外半区),若先移动对象,而某些引用还指向旧地址,就可能读到被覆盖的脏数据,或导致对象被重复移动。forwarding 指针正是为解耦“定位”与“搬运”而设——它让引用更新有据可依,也使移动可安全延迟。
典型实现:Lisp2 算法
Lisp2 是最经典的标记-压缩实现,其结构清晰体现上述逻辑:
- 每个对象头预留 forwarding 字段,初始为空;
- 第一遍扫描填 forwarding(确定去哪);
- 第二遍扫描更新所有跨对象引用(告诉别人去哪找);
- 第三遍真正复制对象(按 forwarding 执行搬迁)。
该算法不要求对象大小一致,适用通用 JVM 堆,但需三次遍历,停顿时间相对较高。
压缩带来的实际影响
压缩后堆呈现“存活区 + 空闲区”的整齐格局:
- 新对象分配只需维护一个指针(如 bump pointer),极快;
- 不再需要复杂空闲链表管理碎片块;
- 但移动对象本身开销大,尤其当存活率高、堆巨大时,GC 暂停时间明显延长。
所以 CMS 放弃压缩,G1 则采用分区+局部压缩策略来折中。
相关文章
- 绝区零希格莉德立绘合集 希格莉德值得抽吗 07-20
- 《明日方舟:终末地》塔晶系统介绍 07-20
- 金铲铲之战s18索拉卡羁绊技能分享 07-20
- 三国志王道天下怎么攻城备战-三国志王道天下攻城备战详解 07-20
- 星轨之上阵型怎么搭 阵型搭配推荐 07-20
- 《饥荒》下雨应对方法 07-20