safe region 解决线程处于 sleep 或 blocked 状态时无法响应 gc 中断的问题,其通过线程在进入非运行态前主动声明“已安全”,使 jvm 可跳过轮询、直接执行 stw;典型位置包括 sleep 前、wait 后、锁竞争失败时及 jni 返回前。

Safe Region 解决的是 JVM 在触发 GC 时,无法让处于 Sleep 或 Blocked 状态的线程主动配合停顿的问题。这类线程不执行字节码,收不到中断信号,也不可能“走到” SafePoint,所以不能依赖 SafePoint 机制。Safe Region 的设计思路是:不等它动,而是提前确认它“已经静止且安全”。
安全区域的本质是“静态可信区间”
它不是某个指令点,而是一段语义上稳定的代码范围——在此区域内,线程的栈帧、寄存器、OopMap 都不再变化,对象引用关系完全冻结。典型位置包括:
- Thread.sleep() 进入 OS 线程挂起前的最后一刻
- Object.wait() 已释放锁、加入 WaitSet、状态切换完成之后
- synchronized 竞争失败、进入 Monitor Contention Queue 前
- JNI 方法返回 Java 层前的过渡阶段(部分 JVM 实现)
线程进入安全区域时主动“报备”
一旦线程确认自己即将进入非运行态,且当前所处位置属于安全区域,就会执行两件事:
- 设置本地标志(如 in_safe_region = true)
- 向 JVM 注册“我已就绪,GC 可跳过我”
此后 JVM 启动 STW 时,不再轮询或等待该线程响应,直接将其视为“已挂起”,保障 GC Roots 枚举的准确性。
线程唤醒后需确认 GC 是否结束
当线程被系统唤醒准备恢复执行时,并不会立刻继续运行,而是先检查 JVM 是否仍在 GC 中:
- 如果 GC 已完成,清除 in_safe_region 标志,正常执行
- 如果 GC 尚未结束,线程会在安全区域内原地等待,直到收到“可离开”信号
这个等待不破坏安全性,因为它仍处在引用关系不变的状态中。
为什么能避免 GC 卡住
没有 Safe Region 时,JVM 面对长时间 sleep 的线程只能干等,导致 STW 无限延迟;有了 Safe Region,JVM 把“安全判断”前移到线程进入阻塞前一刻,把被动等待变成主动声明。本质上,它把“线程必须到达某点才能停”变成了“只要停在某段范围内,就是安全的”。











