记一次排查线上full gc过程

最近频繁收到线上报警,就看看到底啥原因

记一次排查线上full gc过程

二 导出dump文件

2.1 查找报警对应的进程

ps -ef|grep XX

记一次排查线上full gc过程

是23898,看一下gc情况:

记一次排查线上full gc过程

这才不到半小时,fgc就增加了好几次。

jmap导出dump。

jmap -dump:format=b,file=salary1 23898

因为文件相对较大,几百M。直接下载还是比较慢的,所以压缩后下载是快的。

通常zip,tar压缩后是原来的1/10.再大的也可以考虑bz2等别的格式。

三 分析dump

3.1 visualVM 

jdk 自带的,可以去jdk安装目录下面直接打开。

记一次排查线上full gc过程

直观的感受就是实例数里面,AQS的node节点很多。下面的hashmap,ConcurrentHashMap也是值得关注的。

3.2 MAT

在用mat看看。

记一次排查线上full gc过程

     1. Histogram可以列出内存中的对象,对象的个数以及大小。
     2. Dominator Tree可以列出那个线程,以及线程下面的那些对象占用的空间。
     3.Top consumers通过图形列出最大的object。
     4.Leak Suspects通过MA自动分析泄漏的原因。

因为是个web工程,所以,显示web容器是怀疑的对象。

记一次排查线上full gc过程

大量的是线程池的线程。

点进去看Histogram:

记一次排查线上full gc过程

抛出byte[],char[] 还是hashmap占用的多。

搜一下代码看看。

作为一个web工程,典型的MVC应用。

记一次排查线上full gc过程

存在大量的json返回接口,都是使用hashmap实现的。

开发的时候省点时间,实际上不推荐的,定义个对应的bean,fastjson 转成对应的json就好。

效率也比这个好。

2. 在sso代码里面。

 private final Map<Long, String> CITY_NAME = new ConcurrentHashMap<>();

类似这种,读代码后没有任何并发的情况,却滥用了ConcurrentHashMap。

业务目的就是根据cityid获取cityname.放到本地缓存或者redis都行。

常见的模式就是:初始化根据sso接口获取全部城市列表,放到缓存,定时去更新就好,毕竟城市调整的几率小(业务发展新增开通城市)。

后续待业务小伙伴优化后看效果,待反馈。