标记整理(Mark-Compact)通过标记存活对象、将其紧凑迁移至堆起始端、再清理尾部空闲区三步,解决内存碎片问题;它需更新所有引用,开销较大,但保障大对象连续分配。

标记整理(Mark-Compact)不是简单“删掉垃圾”,而是先保住该活的对象,再把它们物理挪到一起,腾出一大块连续空闲空间。
它分三步完成内存回收
整个过程严格按顺序执行,不能跳过或并行:
- 标记(Mark):从根对象(全局变量、栈中引用、DOM 节点等)出发,递归遍历所有可达对象,给每个存活对象打上标记;不可达对象不标记,后续会被清除。
- 整理(Compact):把所有已标记的存活对象,统一往堆内存起始地址方向移动,紧密排列,中间不留空隙;对象位置变了,地址也变了。
- 清理(Sweep):将整理后尾部剩余的大片连续内存直接设为空闲区,供下次分配使用——这一步不逐个扫描,而是直接截断,效率高。
它解决的是内存碎片问题
单纯用标记清除(Mark-Sweep)后,空闲内存像散落的碎砖块,东一块西一块。当需要分配一个较大对象(比如 1MB 的 ArrayBuffer 或长列表缓存)时,即使总空闲量足够,也可能因没有连续空间而失败或被迫提前触发 GC。Mark-Compact 把“碎砖”垒成一整面墙,确保大对象能一次分配成功。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
整理带来的开销和优化
因为对象被移动了,所有指向它的引用都必须更新——比如栈里的局部变量、其他对象的属性、闭包环境中的捕获值。这个重写指针的过程是主要开销来源。
立即学习“Java免费学习笔记(深入)”;
- V8 通过 并行整理(Parallel Compaction) 让多个线程协同搬运对象,缩短主线程停顿时间;
- 它不会每次 GC 都运行,只在 V8 检测到老生代碎片严重(如最大连续空闲块远小于平均空闲块)时才触发;
- 日常开发中,减少长期持有无用对象(如未解绑的事件监听器、意外挂载到 window 的变量、闭包中滞留的大数组),能显著降低每次整理需搬运的对象数量。
它和标记清除的本质区别
标记清除只做逻辑清理:标记 → 清除 → 留下碎片;标记整理多了一步物理迁移:标记 → 挪动 → 清理尾部。前者快但易碎,后者慢但稳——对长时间运行的页面或 Node.js 服务来说,少几次整理,往往比多几次轻量 GC 更省资源。

















