Java 中的 SafePoint

SafePoint 是 Java 代码中线程暂停执行的位置,用于GC暂停、代码优化等操作。线程通过检查 SafePoint 数据结构决定是否暂停。在编译代码中,JIT在适当位置插入检查;解释代码时,JVM切换字节码执行表。当JVM进入SafePoint,运行字节码的线程会修改dispatch table,执行native code的线程在返回Java时检查,JIT编译代码通过polling page检查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是 SafePoint

SafePoint 是 Java 代码中的一个线程可能暂停执行的位置。SafePoint 保存了在其他位置没有的一些运行时信息。SafePoint 保存了线程上下文中的任何东西,包括对象,指向对象或非对象的内部指针。

在 JVM 处于 SafePoint 时,可以做什么呢?

  1. Garbage collection pauses
  2. Code deoptimization
  3. Flushing code cache
  4. Class redefinition (e.g. hot swap or instrumentation)
  5. Biased lock revocation
  6. Various debug operation (e.g. deadlock check or stacktrace dump)

在 JVM 源码的注释里提到,当系统要进入 SafePoint 时,不同状态的 Java 线程的暂停机制是不一样的:

  1. 运行状态的线程必须阻塞。
  2. 不与 JVM 交互的运行 Native Code 的线程能继续执行(如果需要通过 JNI 访问 Java 对象,调用 JAVA 方法,从 Native 回到 JAVA 的话,则必须等到 Safepoint 结束)。
  3. 所有阻塞中的线程,需要等待 SafePoint 结束,才能返回。

Java 线程是如何进入 SafePoint 的呢?

  1. 每个线程通过检查 SafePoint 数据结构的状态来确定是否需要暂停自己来进入安全态。
  2. 对于编译的代码,JIT 通过在代码中适当的位置插入 SafePoint 检查的代码(通常在调用的返回和循环的退出)。
    • JIT 会在所有方法的返回之前,以及所有非 counted loop 的循环(无界循环)回跳之前放置一个 SafePoint,防止发生 GC 需要 STW 时,该线程一直不能暂停。
  3. 对于解释的代码,JVM 保存了两张字节码的执行表,如果需要进行 SafePoint 检查,JVM 会在两张表之间切换。

通常 safepoint 有三种状态:

  1. _not_synchronized:正常运行状态。
  2. _synchronizing:VM Thread 正在等待所有线程进入 safepoint。
  3. _synchronized:所有线程进入 safepoint,VM Thread 可以开始工作了。

程序运行时,可以设置 JVM 参数 -XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1 来输出 SafePoint 的统计信息。

源码分析

当 JVM 要让线程暂停 STW 时,会调用 SafepointSynchronize::begin 方法,该方法在 safepoint.cpp 里。源码地址


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值