深入理解JVM的安全点与安全区域

在JVM中,"世界暂停"(Stop-The-World, STW)是一个很重要的机制。像垃圾回收(GC)这样的核心操作,都要求在一个数据一致的、静止的快照上进行。为了获取这个快照,JVM必须暂停所有正在运行的业务线程。

但是,这个"暂停"操作不能在任意指令上执行,否则可能导致数据处于不一致的状态。为了能够安全、高效地暂停所有线程,JVM设计了一套协作机制,其核心就是"安全点"(Safepoint)和"安全区域"(Safe Region)。

安全点:处理活跃执行的线程

安全点是代码执行流中的一些特定位置。它主要解决的是那些正在CPU上活跃执行的线程如何安全停下的问题。

当JVM需要STW时,它会设置一个全局标志。但它不会立即抢占式地中断线程,而是让这些活跃线程继续执行,直到它们运行到下一个安全点。到达这个特定位置时,线程会主动检查那个全局标志。如果发现需要暂停,它就会保存好上下文,然后主动挂起。

这些安全点的位置并不是随意设置的。JVM并不会在每条字节码后都设置,那样性能开f_da过高。它是在JIT编译时,在一些关键位置插入轮询指令,例如方法调用返回之前,或长时间循环的末尾。这样既能保证线程总会执行到安全点,也控制了性能损耗。

安全区域:协同非活动状态的线程

安全点机制依赖线程主动执行指令去轮询。但如果一个线程当前没有在CPU上执行,它就无法主动到达安全点。

例如,线程可能处于 BLOCKED 状态(等待锁),或者 WAITING 状态(执行了 Object.wait()),也可能正在执行JNI本地方法,此时执行控制权不在JVM。

"安全区域"就是为了处理这类非活动线程而设计的。安全区域是指代码中的一段连续区间,在这段代码执行期间,线程对Java堆中对象的引用关系保证不会发生任何变化。

它的协作流程是:当一个线程将要进入这种非活动状态(如发起JNI调用)之前,它会先标记自己的状态,表明将进入安全区域。

当JVM发起STW时,它会扫描所有线程。如果发现一个线程被标记为"在安全区域内",JVM就知道该线程的引用关系是稳定的,可以不等待它,直接将其视为已暂停。

当该线程完成了操作(如JNI调用返回),准备离开安全区域时,它不能立即恢复执行。它必须先检查JVM的全局STW标志位。如果STW正在进行中,该线程必须自我阻塞,在原地等待,直到STW结束的信号传来,它才能安全地离开。

总结:两者的关系

安全点和安全区域是JVM为实现STW而设计的两个互补的协作机制,共同确保所有应用线程都能在一个一致的状态下暂停。

  • 安全点主要面向正在CPU上活跃执行的线程。它通过JIT在代码中插入轮询点,让这些活跃线程主动在预设的安全位置上自我挂起。
  • 安全区域则解决了处于非活动状态的线程的协同问题,例如那些被阻塞、等待或正在执行本地代码的线程。通过标记进入和检查离开的机制,安全区域确保了JVM在STW时可以不必等待它们,同时也保证了它们在恢复运行时不会破坏内存一致性。

总而言之,安全点解决了活跃线程的暂停问题,而安全区域解决了非活跃线程的协同问题。两者共同作用,才使得JVM能够安全、完整地暂停所有应用线程。

相关推荐
wanhengidc3 小时前
云手机和虚拟机的区别都有哪些?
运维·服务器·安全·智能手机·玩游戏
xixixi777775 小时前
信息安全和网络安全的区分在哪
网络·安全·web安全·信息安全
金仓拾光集5 小时前
__金仓数据库替代MongoDB护航医疗隐私:医院患者随访记录安全存储实践__
数据库·安全·mongodb
newxtc5 小时前
【江苏政务服务网-注册_登录安全分析报告】
人工智能·安全·yolo·政务·1024程序员节·安全爆破
Paraverse_徐志斌6 小时前
异常日志不打印堆栈?谈谈 JVM 的 Fast Throw
jvm·hotspot·堆栈·npe·fast throw
lang201509286 小时前
Spring空安全指南:告别空指针异常
java·安全·spring
学到头秃的suhian6 小时前
Java内存区域
java·jvm
安当加密8 小时前
如何通过掌纹识别实现Windows工作站安全登录:从技术原理到企业级落地实践
windows·安全·1024程序员节
广州华锐视点9 小时前
电力电网安全实训难题多?VR安全教育软件给出新方案
安全