背景
在公司外部技术群里,常常有人时不时的问到服务某次GC工夫忽然很高,有什么方法排查。基本上每次都会有人狐疑会不会Swap导致的,先看看Swap,如果真的应用了Swap区域,基本上就会让Swap区域背锅了。
案例
案例一:CMS GC工夫飙升
有次群里有人给出一个case:CMS GC工夫飙升,次要是remark阶段的解决工夫太长,给出的日志如下:
群里有人应用到了Swap区域。而对CMS GC如果有理解的话,想问的必定是是不是加了“-XX:+CMSScavengeBeforeRemark
”这个参数。在明确告知有这个参数。然而我在这个remark阶段并没有看到young gc,提问者就又截了一个全一点的日志,如下:
感觉日志在remark之前并没有进行young gc,失常的退出“-XX:+CMSScavengeBeforeRemark
”参数日志应该如下:
于是又让提问者确认一下,在remark工夫失常的状况下是不是进行了young gc,在remark工夫异样的状况下没有进行young gc,失去的答案是。那么问题基本上就转化成了“为什么在remark之前没有进行young gc呢”
而后带着这个问题去Google基本上就比拟容易找到答案了,根本能够概述为在执行JNI时候,有可能会导致JVM阻止执行young gc。能够参考:
答案一
答案二
退出参数:+PrintJNIGCStalls能够验证该问题。
案例二:Young GC 工夫飙升很高
这个笔者经验的一个case,监控&日志如下:
因为gc log中只能看到GC总工夫看不到哪个阶段呈现问题,所以把垃圾回收齐切换到G1,看到的log如下:
发现Termination比拟久,Object copy diff 太大导致的,也就是CPU忙碌水平不统一导致的,批改gc 线程数小于 cpu问题解决。
如何判断是不是Swap区域导致GC异样
如果JVM堆内内存大于等于零碎内存的话,Java过程呈现了大量应用Swap区域对GC影响的确比拟大。如果产生GC抖动时,零碎没有应用Swap区域或者Java过程没有应用Swap区域,就能排除Swap起因。
因为我司只对系统应用Swap区域的整体状况做了监控,并未对Java过程应用Swap区域做监控,GC抖动基本上是小概率事件,所以很难从监控做出判断的。
那么其余状况,如何大抵判断进去是不是Swap导致的GC异样呢?
首先,咱们得理解Swap相干的基本知识。
Swap区域次要解决外部有余的问题,把局部硬盘当做虚拟内存应用。
Swap中最要害的零碎参数:vm.swapiness(0-100),该参数值越小示意当内存不足时,偏向于通过回收cache区域,而不是把过程内存替换到Swap区域。所以该值应该设置小一点就能缩小Swap可能对GC产生的影响,比方我司对立默认设置为1。
Swap内存回收算法应用的是LRU算法,他会标记处沉闷页面和非沉闷页面,也就是说如果内存始终被应用基本上常驻内存,不会被替换到Swap。
GC的哪些阶段可能受Swap影响
young gc
young gc的特色是较为频繁,基本上每分钟都会屡次。young gc次要有两个阶段,一个是扫描阶段、一个是对象复制阶段。扫描阶段会从根汇合扫描标记Eden、From中的存活对象,而后对象复制阶段把存活对象copy到To区域中去。
复制阶段:因为young gc较为频繁就会导致Eden、From、To区域不太可能被置换到Swap区域,所以复制阶段不太可能受到Swap区域影响;假如young gc不频繁,那么在刚刚经验了扫描阶段,Eden、From也必定会在内存中,只有To区域有可能会受到Swap影响。
相比拟于复制阶段,扫描阶段就绝对简单一点。这次要跟根汇合有关系,young gc的根汇合次要有线程上下文、old区域、Class、JNI援用等,像JNI援用、Class等长时间不应用有可能被OS置换到Swap。所以该阶段有可能因为Swap影响GC。
cms gc
cms gc次要分为:初始标记、并发标记、并发预清理、从新标记、并发清理等阶段,只有初始标记和从新标记会stop the world,所以咱们只须要关注这两个阶段即可。
初始标记:该阶段标记GC Roots能间接关联到的对象。所以该阶段和young gc的扫描阶段相似,也有可能因为Swap影响到GC。
从新标记:因为在并发标记和并发预清理这个阶段,用户线程和GC 线程并发,如果这个阶段用户线程产生了新的对象,总不能被 GC 掉吧。这个阶段就是为了让这些对象从新标记。在这个阶段拜访到的内存肯定是之前刚刚拜访过的,所以这个阶段不太可能由Swap区域导致GC异样。
总结
对于CMS GC,如果在remark阶段异样行为而InitialMark是失常的,基本上能够排除Swap导致的GC,young gc在copy阶段异样而Root Scaning失常也基本上能够排除Swap因素。
我想大家喜爱让Swap背锅的起因有两个:
- 对Swap如何影响GC以及可能影响到GC哪些阶段不太理解;
- GC工夫异常情况下,的确较难剖析和排除;必须要对GC的具体过程,GC工具等有较为深刻的理解。
参考: 《2020最新Java根底精讲视频教程和学习路线!》
链接:https://juejin.cn/post/691651...