记一次线上JVM长时间STW之分析(上)

这两天再捣鼓一个JVM长时间STW的问题,看了不少文章,怕过两天就忘掉了,还是写点东西记录下来,虽然到目前这一刻还是没找到root cause,但是期间却学到不少东西,记下来也是很有价值的。

话不多说,先上问题


在线上的JVM我们发现最近一些比较奇怪的毛刺,在此之前,我们遇到一些GC 的毛刺,是因为没有硬性配置CMS的Initial Mark的时刻导致,根据JVM自己的算法,把CMS启动时间搞到90% 多的HEAP时刻,导致回收失败总是触发Full GC导致,后来通过硬性配置 CMS的Initial Mark 解决了那个毛刺的问题。看上图可知,这次明显不是GC惹的祸。
从图中可以看到,在偶然的一些时刻,会有非常长时间的STW时间(1.5秒),而从下图看到,虽然这次的STW是由GC触发的(GenCollectForAllocation),但是时间杀手并不是GC, 从下图打印的SafePoint statistics 的table看到,时间都花在了 block阶段,也就是在等待JVM线程进入安全点导致,而GC仅仅用了116毫秒。
网上google了一把,几乎没有人提问过为啥block很长这种情况,因此只好去挖挖文章,学习一下JVM的SafePoint原理了。

首先是先去了解什么是SafePoint,挖到一篇不错的文章

JVM源码分析之安全点safepoint

简单总结几句就是说,我们通常以为,JVM STW 很多情况都是因为要GC,其实不然,在JVM里需要STW的情况有下面几种

  • Garbage collection pauses
  • Code deoptimization
  • Flushing code cacheClass redefinition (e.g. hot swap or instrumentation)
  • Biased lock revocation
  • Various debug operation (e.g. deadlock check or stacktrace dump)

而,在STW之前,JVM需要做的第一件事,就是去把所有的JVM Thread block住,专业点来讲,就是在JVM里安排了一个安全的代码区域叫SafePoint,只要线程跑到了这些安全域,就认为挂起这些线程是安全的。这篇文章详细讲解了几种进入安全域的方法,这里就不再赘述了。

那这个进入SafePoint是不是一个好惹的鸟呢,好惹的话哥就不用写这篇文章了,也不会有这么多程序员被拿去祭天了,进入SafePoint的每个阶段代表什么呢,又有哪些手段可以检测呢?(比如我上面贴问题那两张图),接着我又去拜读了江南白衣文章

JVM的Stop The World,安全点,黑暗的地底世界

上面文章降到可以如何去检测这个ApplicationStopTime,并且解释了那几个字段的含义,这里为了好看,也贴一下:

此日志分两段,第一段是时间戳,VM Operation的类型,以及线程概况
total: 安全点里的总线程数
initially_running: 安全点时开始时正在运行状态的线程数
wait_to_block: 在VM Operation开始前需要等待其暂停的线程数

第二行是到达安全点时的各个阶段以及执行操作所花的时间,其中最重要的是vmop
spin: 等待线程响应safepoint号召的时间
block: 暂停所有线程所用的时间
sync: 等于 spin+block,这是从开始到进入安全点所耗的时间,可用于判断进入安全点耗时
cleanup: 清理所用时间
vmop: 真正执行VM Operation的时间

本人语文理解能力比较差,所以当时看到spin 和block,我的理解spin就是JVM发出global SafePoint响应时,所有线程都接收到这个信号的时间,而block 就是所有线程需要跑到安全点的时间。
这就直接导致了我去想问题的方向,最终是错误的,知道后来又找到另外一篇文章的解释

java GC进入safepoint的时间为什么会这么长?

在这篇文章,它是这么介绍的

2.2 Stop The World的四个阶段
根据-XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1 参数虚拟机打印的日志文件可以看出,safepoint的执行一共可以分为四个阶段:

  • Spin阶段。因为jvm在决定进入全局safepoint的时候,有的线程在安全点上,而有的线程不在安全点上,这个阶段是等待未在安全点上的用户线程进入安全点。
  • Block阶段。即使进入safepoint,用户线程这时候仍然是running状态,保证用户不在继续执行,需要将用户线程阻塞。http://blog.csdn.net/iter_zc/article/details/41892567** 这篇bog详细说明了如何将用户线程阻塞。
  • Cleanup。这个阶段是JVM做的一些内部的清理工作。
  • VM Operation. JVM执行的一些全局性工作,例如GC,代码反优化。
    只要分析这个四个阶段,就能知道什么原因导致的STW时间过长。

再加上Ivy今天的指点,发现和我之前的理解是出入非常大的,最后我是这么理解的,Spin阶段其实就是所有线程跑到了SafePoint 的时间(这个时间一般有长有短,具体看你的JVM 线程都在干嘛,比如线程再跑右边界的大for循环,那么就得等了,这也是在网上能搜到的一般程序员遇到的,就是Spin很长导致最后Sync很长),而 block 阶段则是JVM让所有线程 Block锁花费的时间了,具体JVM是怎么让JVM Thread 阻塞的呢?推荐仔细看下面两篇文章:

聊聊JVM(九)理解进入safepoint时如何让Java线程全部阻塞
聊聊JVM(六)理解JVM的safepoint

如果简单几句话描述的话,就是要视乎当前的JVM Thread在跑什么,比如Java Code? 还是Native调用? 等,然后措施就是让这个线程去OS 去load 一个锁住的Page, 这样的话这个线程发送内核命令去Load Page却Load不到,自然而然就挂起了。

那再回过来我们的问题,怀疑的点就变成很窄了,原本这个系统调用是非常迅速的,很可能就是OS在做自己的IO,比如swapping等,进行了进程上下文的切换,导致根本想去响应这个调用,因此再回来时自然这个操作就耗时了(还记得这个问题吗?就是block 用了1.3s)。
由于线上我们并没有配置SafePoint超时和配置SafePoint超时打印线程状态,因此我们也只能猜测了,最后一种可能就是线程在做状态切换时被阻塞了,注意,这里所说的线程状态是JVM里面对应的VMThread ,而不是传统的Java Thread,大家可以看看下面这篇文章:

聊聊JVM(五)从JVM角度理解线程

看个大概吧,具体深入的CPP我也没仔细去看了,又和Ivy讨论了一番,最后得出结论是,这个损耗应该也是计算在spin里面的而不是block 的耗时。


后话

猜测终归是猜测,在实验室环境压测了2天,也没抓到什么罪证,最大的可能的的确确就是OS在进行上下文切换了,看对症下药做点措施再继续观察了。
收官时刻,突然院长又冒出另外一个问题(巨坑啊啊啊啊啊):CMS 如果不配置 Eden比例的话,默认是很小的,终于发现我们的频繁的YGC是有原因的,哈哈哈,今天一并把这个也该了,希望上面遇到的问题也是因为YGC太频繁而导致的。

目前是加上了 -XX:NewRatio=2 了,GC看起来平滑了N倍。

image.png

至于这个问题:还是等解决了一切其他问题后再回来看吧。。。。。。。。

(待续)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容