Total time for which application threads were stop 超级长时间,这行日志代表什么,以及为什么时间会这么长 ?
Total time for which application threads were stopp 2.81 seconds,Stopping threads took :2.6 seconds
当GC发生时,每个线程只有进入了SafePoint才算是真正挂起,也就是真正的停顿,这个日志的含义是整个GC过程中STW的时间,配置了 -XX:+PrintGCApplicationStoppedTime 这个参数才会打印这个信息。
重点:第一个 2.81 seconds 是JVM启动后的秒数,第二个 2.6 seconds 是 JVM发起STW的开始到结束的时间。特别地,如果是GC引发的STW,这条内容会紧挨着出现在GC log的下面。
有关安全点的详细说明,请移步:
JVM源码分析之安全点safepoint
[Java JVM] Hotspot GC研究- GC安全点 (Safepoint&Stop The World)
等待所有用户线程进入安全点后并阻塞,做一些全局性操作的行为。
Garbage collection pauses(垃圾回收)
JIT相关,比如Code deoptimization, Flushing code cache
Class redefinition (e.g. javaagent,AOP代码植入的产生的instrumentation)
Biased lock revocation 取消偏向锁
Various debug operation (e.g. thread dump or deadlock check) dump 线程
配置 -XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1 参数,虚拟机会打印如下日志文件:
-XX:+PrintSafepointStatistics 打印安全点统计信息, -XX:PrintSafepointStatisticsCount=n 设置打印安全点统计信息的次数;
vmop:引发STW的原因,以及触发时间,本例中是GC。该项常见的输出有: RevokeBias、BulkRevokeBias、Deoptimize、G1IncCollectionPause 。
数字306936.812是虚拟机启动后运行的秒数。GC log可以根据该项内容定位Total time for which application threads…引发的详细信息。
total :STW发生时,JVM存在的线程数目。
initially_running :STW发生时,仍在运行的线程数,这项是Spin阶段的 时间来源
wait_to_block :STW需要阻塞的线程数目,这项是block阶段的时间来源
sync= spin + block + 其他。
RevokeBias、BulkRevokeBias、偏向锁取消情况。
Deoptimize、
G1IncCollectionPause GC GC 执行情况。
分析 -XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1 产生的日志信息基本上STW的原因都是RevokeBias或者BulkRevokeBias。这个是撤销偏向锁操作,虽然每次暂停的 时间很短,但是特别频繁出现也会很耗时。
一些高并发的系统中,禁掉JVM偏向锁优化,可以提升系统的吞吐量。禁用偏向锁的参数为: -XX:-UseBiasedLocking
线上配置 -XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1 参数,虚拟机打印如下日志文件:
果然是撤销偏向锁搞得鬼, 增加 -XX:-UseBiasedLocking 后, 问题得到解决.