java Young GC排查

最近线上某站点young gc有点频繁,经过排查确定了问题,这里记录一下
遇到GC,三步走 
1. 确认是哪些对象引起的GC 
2. 找到这些对象是哪里构造的
3. 根据情况进行优化。 

一般情况下,我们可以通过jmap dump的方式把堆dump出来进行分析,但dump出来的是一个静态文件。反应的是某一时刻的情况, young gc 中的对象存活时间较短,dump出的文件不一定能反应出问题,所以这里我使用了jmap histo(注意:这里的jmap histor只是显示对象的个数和大小,如果要知道对象属性的值,还是要dump)

jmap -histo pid  #如果使用jmap -histo:live pid 则会触发一次full gc

这个命令会显示Java堆中的对象的个数和总大小,并且按照大小排列。 这里我们并不需要这么多。 

jmap -histo pid| sed -n '3,23p' 

这里只取了前20条, 这个命令只能反应某一时刻的情况,如果想要持续观察

watch -n 5 -d   'jmap -histo pid | sed -n '3,23p''

上面的命令 每5S刷新一次,可以看到有变化的对象

watch -n 5 -d 'jmap -histo pid | sed -n '3,23p' >> obj.log'

上面的命令是将数据记录到文件,我们可以让命令持续2分钟(尽量保证能经历2次GC),然后从服务器上拿到这个文件,写一个python脚本进行解析,解析出来后,导出到excel ,并用透视图绘制成折线图。

这里基本就可以看出来会被GC的对象。 

找出了被GC的对象,接下里就是找出这些对象在哪里构造的,如果这个对象只有一个地方被构造,则可以直接定位到,如果在多个地方被构造,则需要找出被构造最多次的地方。 这里直接借助阿里的Arthas。

stack xx.xx <init>  #<init> 表示构造函数

这里就是找出哪里在调用该类的构造函数,并且打印出堆栈,结果可能会很多,导出来,根据堆栈信息,找出top1, 可以导出多次,最后汇总。 

这里根据堆栈信息找到了代码,根据代码,分析了上下文,发现有些对象可以复用, 这里采用了享元模式, 把其中一些对象改为支持单例模式,至此结束。
当然根据实际情况, 优化的方式不限于代码,也可以调整一些JVM参数,比如新生代的内存大小等。 
原文地址:https://www.cnblogs.com/beyondbit/p/13225869.html