记一次由JVM的GC导致的问题分析
首先感谢阿飞哥,你假笨,吴哥等技术大咖的指点。
转载请注明原创出处,谢谢!
推荐阅读
现象
由于某些原因,我们公司的线上服务器有些操作有超时情况,类似一些回合战斗里,这个回合的战斗一直不能运行,发生超时现象。
处理一
出现超时第一反应,应该是死循环和死锁问题。于是查看服务上的cpu情况。(这里不多做描述可以看你假笨的文章),显然不太像CPU死循环的问题。至于死锁,其他服新的服务器不太容易出现,玩家也很多。于是觉得第一思路不太可行。
处理二
既然CPU的关系不大了,应该转向别的地方。当然这个思路当然这个思路是将线上服,拉取到本地运行,然后做某些操作的时候感觉出来的(可能这感觉是假的)。某些时刻,所有操作都挺卡,凭感觉来说一些线程出问题了,有死循环,其他的线程应该运行良好才是,所以把目标瞄准到了JAVA虚拟机上。
然后将线上服务器拉取到本地来运行,某些时刻操作响应很慢,之后一些操作超时也出来了。(局域网里所以我不太愿意去怀疑网络)
用JAVA自带的工具jconsole连上自己本地运行的程序,然后模拟线上操作,情况出现了。Eden区出现了高频的gc。这个时间正好的是做操作的时间,更加确信是JVM的问题了。然后配置了一下虚拟机环境,这个问题得到了很好的解决。
本地将JVM参数设置成 -Xms4000m -Xmx4000m -Xmn 1200m 问题解决
8G电脑(默认配置的时候)最后发现线上的这个服确实有Eden区配置比较小,导致一些时间里,超频的GC。
现象二
现象一很好的解决了,但是某一些特别的服还是,再整点会有超时现象。明明想着问题解决了居然还有问题。
处理三
接着上次的经验继续怀疑JVM,于是区线上跟踪。用jstat -gcutil pid 1s继续跟踪。问题暴露出来了,再整点开始到第10分钟这段时间里发生了近10次FGC。(图不是原图了。)
再通过执行jmap -histo PID > PID.log 来观察发现确实又三个特别大的对象,其中Object也很反常。(周五才弄下来还没去看object。)
然后再看到这个老年代成长很快,有的时候一次成长3%。吓死宝宝了。
最后发现是容器(list)中存了很多对象,又去遍历所有对象,这些对象一直被list引用不能释放,然后晋升到了OLD区。整点的时候这个现象特别明显A对象48W个实例,B对象52W个实例。
总结
最搓的方法,调整内存,他就不会去FGC了,好吧6G已经给他很大了,还是优化代码吧!(待我将代码完全优化后继续下一篇)
广告时间
关注老铁的公众号,从小菜比到老菜比
你假笨
462563010加QQ群一起学习