jvm的SafePoint

4 篇文章 0 订阅
垃圾收集通常会导致stop the world,但并不是stop the world的唯一途径,应该说应用程序只要到达safepoint就会触发stop the world。

safe point 

在到达safe point后,jvm里的所有工作的应用线程都会被挂起,只有垃圾收集的native线程会持续不断地跑。

因为只有保证垃圾收集线程对jvm中地数据结构具有独占式的访问权限,它才能够做一些诸如标记GC Root 或是 移动堆中对象之类 或是 替换方法栈中的方法 之类的操作。

为何jvm要让应用线程进入safe point

  • 停顿下来进行垃圾回收
  • 指令重排以进行代码优化
  • 清空代码缓存
  • 类重新定义,类似于hot swap热部署
  • 下载threadDump或者heapDump的时候

safe point问题定位

真正线上,除了GC,其他进入safe point的原因都可以不必关注。但如果真的发生了异常,可以使用如下参数进行调优:

-XX:+PrintGCApplicationStoppedTime – 这个不论是gc还是啥,只要进入了safe point,都会打印具体耗时。不幸的是它的输出结果缺少时间戳,但也足够我们缩小问题范围。

XX:+PrintGCApplicationConcurrentTime 和上面的命令相似但不同,它表示在两次应用线程进入safe point 之间,应用线程存活了多长时间。

-XX:+PrintSafepointStatistics  –XX:PrintSafepointStatisticsCount=1  这两个选项会让jvm报告每次进入safe point的原因和耗时,并打印在stdout上,而非gc.log。

safe point工作原理

每个应用线程到达safe point后,都会安全地将自己挂起。jvm有两种字节码运行方式,预编译和即时编译(JIT),safe point机制需要保证在这两种方式下都能正常运行。

我们知道,java是一个典型的两段式编程语言,java编译器将项目源码编译为字节码,再由jvm运行字节码。jvm有两种方式运行字节码

  1. 一种是JIT方式(Just in time),也就是在运行的时候,即时地将bytecode转化为cpu可以识别的native指令。
  2. 一种是提前编译,将java代码直接编译成类似c++一样的语言,编译完后再运行。

JIT即时编译会在方法return后、调用结束后、跳出循环后等时机让应用线程进入safepoint,因为本着“不能让应用线程跑太久一直不进入safepoint”的原则,因为如果致大量线程一直无法进入safepoint,而GC线程也在等待这个应用线程进入safepoint才能开始GC,结果JVM就相当于被冻结了。

JIT编译的时候直接把safepoint的检查代码加入了生成的本地代码,当JVM需要让Java线程进入safepoint的时候,只需要设置一个标志位,让Java线程运行到safepoint的时候主动检查这个标志位,如果标志被设置,那么线程停顿,如果没有被设置,那么继续执行。

例如hotspot在x86中为轮询safepoint会生成一条类似于“test %eax,0x160100”的指令,JVM需要进入gc前,先把0x160100设置为不可读,那所有线程执行到检查0x160100的test指令后都会停顿下来。

0x01b6d627: call 0x01b2b210 ; OopMap{[60]=Oop off=460}; *invokeinterface size; - Client1::main@113 (line 23); {virtual_call}

0x01b6d62c: nop ; OopMap{[60]=Oop off=461};*if_icmplt; - Client1::main@118 (line 23)

0x01b6d62d: test %eax,0x160100 ; {poll}

0x01b6d633: mov 0x50(%esp),%esi

0x01b6d637: cmp %eax,%esi

在解释器执行方式下,JVM会设置一个2字节的dispatch tables,解释器执行的时候会经常去检查这个dispatch tables,当有safepoint请求的时候,就会让线程去进行safepoint检查。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值