标记-整理算法不靠运气避免崩溃,而是通过写屏障拦截引用变更、转发指针维持临时可达性、STW边界控制三重机制协同保障;转发指针作为移动时的临时路标实现自动重定向,写屏障确保引用精准修正,STW则为安全收敛提供前提。

标记-整理算法在物理内存块移动时,应用线程不会崩溃,根本原因不是“靠运气”,而是靠三重保障机制协同作用:写屏障拦截引用变更、转发指针(或记忆集)维持临时可达性、以及严格的STW边界控制。它不追求“边移动边运行”,而是把高危操作收束在可控窗口内。
转发指针是对象移动时的“临时路标”
当一个对象从旧地址A被复制到新地址B后,JVM会在原位置A处写入一个指向B的转发指针(forwarding pointer)。此后任何对A地址的访问(比如某个栈变量还存着旧引用),都会被GC逻辑或硬件/软件机制自动重定向到B:
- 部分收集器(如Serial Old)在标记-整理阶段全程STW,用户线程已暂停,不存在“正在读A却A已被挪走”的竞争;
- 即使在支持并发整理的ZGC中,通过着色指针+读屏障,每次加载对象前先检查指针颜色和转发状态,命中旧地址就自动跳转并更新引用——这个过程对应用透明;
- 转发指针只在整理阶段有效,整理完成后JVM会批量修正所有外部引用,再清除转发指针,避免长期开销。
写屏障确保引用更新不遗漏
移动对象本身只是第一步,更关键的是让所有指向它的引用同步更新。JVM借助写屏障(write barrier)在每次赋值操作(如obj.field = newRef)时插入钩子:
- 若被赋值字段原指向一个待移动对象,写屏障会记录该字段位置(进入“卡表”或“记忆集”);
- 整理阶段结束后,GC线程扫描这些记录,精准修正所有“悬空引用”;
- 这比遍历整个堆找引用快得多,也避免了漏改导致的野指针或崩溃。
STW不是偷懒,而是安全底线
老年代标记-整理默认要求全程Stop-The-World,并非设计缺陷,而是主动取舍:
- 存活对象占比常超90%,若允许用户线程并发修改引用,漏标+漏改风险极高;
- STW保证了“标记结果稳定”和“移动期间无新引用产生”两个前提,使转发与修正可收敛;
- 现代优化(如G1的局部整理、ZGC的并发转移)本质是把STW压缩到毫秒级“初始标记”和“最终标记”阶段,而非取消它。
所以它不靠“不崩溃”,而是靠“不让崩溃发生”——用机制堵住所有可能的引用错位路径。不复杂但容易忽略。

















