如何理解Java虚拟机的安全点(Safepoint)_垃圾回收暂停时刻原理

胖宇小哥_2888

胖宇小哥_2888

2026-03-23

1007人浏览

原创

因为JVM不强制中断线程以防破坏引用一致性,Safepoint是编译器插入的暂停点,位于方法进出、循环末尾、异常抛出后、调用Java方法前;纯计算长循环无Safepoint会导致STW延长。

如何理解java虚拟机的安全点(safepoint)_垃圾回收暂停时刻原理

为什么 GC 时线程不是立刻停,而是“等它自己走到安全点”?

因为 JVM 不会强制中断线程——那样可能卡在寄存器未刷新、对象引用正被修改、栈帧处于中间状态的位置,导致 GC 扫描到错误的根集合(GC Roots),把活对象当垃圾回收,或漏掉该回收的对象。Safepoint 就是编译器提前埋好的“停车区”,只允许线程在这些位置暂停:方法返回前、循环末尾、异常抛出后、调用其他 Java 方法前。此时栈帧完整、局部变量可枚举、所有引用关系稳定。

常见错误现象:while(true) { long x = System.nanoTime(); } 这种纯计算长循环里没方法调用、没循环跳转,JIT 不会插 Safepoint 检查,线程就一直跑,GC 只能干等,造成 STW 时间飙升(比如从 10ms 拖到 500ms)。

  • 解决办法:在循环体内加一个轻量调用,比如 Thread.onSpinWait()(Java 9+)或 System.nanoTime()(触发隐式检查)
  • 验证方式:启动时加 -XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1,看日志里 “Time to wait for sigal” 和 “No vm operation” 的延迟是否异常高
  • 注意:JNI 线程不主动轮询,但一旦从 native 返回 Java 代码,必须立即检查一次 —— 所以长时间阻塞在 read() 或 pthread_cond_wait() 里的线程,不会拖慢 Safepoint 进入

哪些代码位置天然有 Safepoint?哪些没有?

HotSpot JIT 编译器按确定规则插桩:方法入口/出口、循环回边(loop back-edge)、方法调用前、异常处理表入口。解释执行时靠字节码分发器隐式检查,所以也基本覆盖。

真正危险的是“无 Safepoint 区域”:

  • for(long i = 0; i :JIT 可能优化掉循环检查,且无方法调用 → 无 Safepoint
  • Unsafe.copyMemory() 或 VarHandle.setOpaque() 的密集使用:底层绕过 JVM 控制,若在关键路径上,需人工插入 Thread.yield()
  • 内联深度过大的热点方法:JIT 可能省略部分 Safepoint 插入(尤其循环嵌套深时),可通过 -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation 查看编译日志中的 safepoints 字段

怎么确认自己的应用被 Safepoint 卡住了?

不能只看 GC 日志里的 “GC pause” 时间 —— 那只是 STW 总耗时,不区分“等线程停”和“真正在 GC”。真正要盯的是线程进入 Safepoint 的等待时间。

Java调试
Java调试

通过 JDWP 实现 Java 远程调试:连接远程 JVM、设置断点、单步执行代码、查看变量值、获取调用栈。适用于需要调试远程 Java 应用、排查运行时状态、追踪代码执行流程的场景。 术语注解 JDWP:Java Debug Wire Protocol,Java 调试有线协议(Java 远程调试底层通信协议) remote JVM:远程 Java 虚拟机 step through code:代码单步调试(步入 / 步过 / 步出调试) inspect variables:变量查看 / 变量检视 stac

下载

实操建议:

  • 加参数 -XX:+PrintGCDetails -XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1,观察输出中 “vmop” 行的 time stamps 字段,重点看 spin 和 block 时间是否显著大于 cleanup 和 vmop
  • 用 jstack -l 抓线程快照,如果大量线程停在 java.lang.Thread.sleep(Native Method) 或 sun.misc.Unsafe.park(Native Method),说明它们本就在安全状态;但如果一堆线程卡在 java.util.Arrays.copyOfRange 或自定义计算方法里不动,就要怀疑 Safepoint 延迟
  • 生产环境慎用 -XX:+SafepointTimeout(默认关闭),开启后超时会打印警告,但仅作诊断,不自动修复

SafeRegion 是什么?和 Safepoint 有什么区别?

SafeRegion 是 Safepoint 的补充机制,专治“线程本来就停着”的情况。比如线程调用了 Object.wait()、Thread.sleep()、或阻塞在 Socket.read() 上 —— 此时它已不修改堆内存、不变更栈帧,本身就是安全的,没必要等它“走到”某个插桩点。

JVM 把这类阻塞入口标记为 SafeRegion 起点,出口标记为终点。线程一进入就声明“我现在安全”,离开前再检查一次 Safepoint 标志。这样既避免空等,又保持语义一致。

开发者容易忽略的一点:如果你写了一个自定义锁,内部用 Unsafe.park() 实现阻塞,但没配合 Thread::onSpinWait 或显式进入 SafeRegion(需 JVMTI),那这个线程在 park 期间仍可能被 Safepoint 机制误判为“不可达”,导致 GC 等待时间虚高。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

java java虚拟机

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

11937

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

9022

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

7732

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1264

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

1008

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1516

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

3129

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20371

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1375

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习