在高并发下,Java程序的非正常GC带来的影响往往会被进一步放大。不管是「GC频率过快」还是「GC耗时太长」,由于GC期间都存在Stop The World问题,因此很容易导致服务超时,引发性能问题。本期小编为大家筛选了4篇Young GC问题排查文章,帮大家复习YGC的执行原理和问题排查要点。
1.YGC问题排查,又让我涨姿势了!
作者:Rockets
https://heapdump.cn/article/1...
本文作者分享了一个棘手的Young GC耗时过长的线上案例,首先是收到服务超时告警,发现了YoungGC耗时过长的问题,然后就开始排查。发现问题后的处理堪称教科书般的操作:“按照GC问题的常规排查流程,我们立刻摘掉了一个节点,然后通过以下命令dump了堆内存文件用来保留现场。jmap -dump:format=b,file=heap pid
最后对线上服务做了回滚处理,回滚后服务立马恢复了正常,接下来就是长达1天的问题排查和修复过程。”
经过确认JVM配置——检查代码——对dump的堆内存文件进行分析——分析YGC处理Reference的耗时——再回到长周期对象进行分析,找出了问题所在:每次调用getConfig方法时都会往List中添加元素,并且未做去重处理,然后立即解决了问题。
文末对YGC相关知识点进行了梳理和总结,从新生代的相关知识讲起,带大家复习了YGC的触发时机和执行过程。
本文是一篇理论与实战结合的经典好文,作者不仅分享了自己遇到YGC问题的排查思路,还就此知识点帮大家复习了原理。读者今后遇到类似的问题可以参考快速分析解决。
2.频繁操作本地缓存导致YGC耗时过长
作者:阿菜
https://heapdump.cn/article/1...
本文作者在帮群友排查YGC耗时过长问题,通过分析堆栈和GC log发现,在某次YGC时,Survivor区中年龄超过7的对象占用了Survivor空间一半以上。而正常情况下,年轻代对象朝生夕死。网络服务处理请求为毫秒级,YGC几秒甚至十几秒才发生一次,多数年轻对象活不过1代。于是,猜测该群友使用了本地缓存。进一步沟通后得出结论:原因一:年轻代中有太多存活的对象,增加了标记时间;原因二:YGC又需要花费大量的时间在扫描Card Table上,总结原因是操作本地缓存太频繁导致了YGC耗时过长。最后向群友提出了修改意见解决了问题。
在文章结尾作者还总结了该业务场景的几条修改建议,很有参考价值。
3.我司基础组件更新本地缓存策略问题导致young gc时间升高
作者:朱纪兵
https://heapdump.cn/article/1...
本文作者在一次研究服务QPS和young gc的时间的关系时,发现实际情况与理想状态不同,于是开始追踪问题。用gdb 去dump了下来survivor区域中的内容,发现了异常点。最后发现是公司配置中心基础组件更新本地缓存策略的问题。
作者遇到问题不忽视主动排查反复验证的精神值得学习。
4.耗时20多秒的young gc,你见过吗?
作者:Edenbaby
https://heapdump.cn/article/1...
作者遇到了耗时20多秒的young gc,在排查时发现user(用户耗时)+sys(系统耗时) <real(真实耗时),但大多数的young GC中,real time是小于sys+user time的,因为paralle垃圾回收器是多线程并发的去GC,所以user time是各个线程累积的一个时间,大概率要大于real time。因此猜测是CPU不够用或磁盘IO压力大导致的。
排查YGC异常问题,一定要掌握GC执行过程,会看GC log,从日志中找到突破点。
更多性能文章,请访问 https://heapdump.cn/