记一次OOM的分析

前言

测试同学反馈测试环境不能正常访问,查看日志发现OOM。虽然是测试环境,但是还是排查了一下原因,以免线上也出同样的问题。

处理步骤

1、保留现场

首先使用jmap -heap pid查看堆空间使用情况,结果发现年轻代和老年代空间都满了
记一次OOM的分析
还能看到的信息是JVM使用的垃圾收集器是Parallel Scavenge + Serial Old。
保留现场:
1.使用jmap -histo pid > 2020-02-21-erp-web.histo保留类的实例占比统计信息;
2.使用jmap -dump:format=b,file=2020-02-21-erp-web.dump pid > 2020-02-21-erp-web.dump保留dump文件,这个很重要;

2、尽快恢复环境

1.堆内存确实配置的有点小了,才512M,调整JVM的堆最大最小内存为1024M,-Xms=1024m -Xmx=1024m;
2.重启程序;
3.虽然是测试环境,但是也有很多人在用,必须尽快恢复,若是线上环境更应如此。

3、分析dump文件,找到原因

3.1分析工具用什么?

可选的工具有mat,jvisualvm,jhat,推荐用mat,jvisualvm勉强能看出点有用信息,但是远远不如mat好用,jhat真心觉得没啥卵用。

3.2 下载mat

下载链接: https://www.eclipse.org/mat/downloads.php
下载后解压即可运行

3.3 开始分析

3.3.1 先看看histo文件

先看下histo文件的前20行,看看有哪些类是项目中定义的,大概有个印象。

3.3.2 使用mat工具打开dump文件

File->Open File,选择准备好的dump文件,稍微等待一会儿,分析需要一点时间,等待时间视dump文件大小而定,越大等的越久。

3.3.3 概述介绍

记一次OOM的分析
Histogram其实就是上面用jmap -histo导出的信息,所以直接看这里也行,感叹mat真香;
Leak Suspectes个人感觉最有用的存在,我主要也是从这里去分析找问题原因;
Dominator Tree以树的形式列出最大对象以及哪些对象引用的这些对象,比较有用,时间充裕时可以点开看看研究研究;
Top Consumers按类或包列出最“昂贵”的对象,其实也就是空间占比最多的那些对象,也比较有用,时间充裕时可以点开看看研究研究;
其他的感觉用处就不大了。

3.3.3 Leak Suspects分析

记一次OOM的分析
可以看到mat分析认为可能存在三个泄露疑点,其中疑点(a)占堆内存的比例最大;
记一次OOM的分析

分析疑点1

mat分析出710个TaskThread实例占用了159790952/1024/1024=152M的内存空间,但是仅从TaskThread这个类无法判断出更有用的信息,好在mat细心的列出了占内存最大的几个实例,@0xe68bc3c0是实例的内存地址,然后下面又会介绍一个牛逼的工具:
记一次OOM的分析
点击确定出现以下界面:
记一次OOM的分析
关注Retained Heap值比较大的项,但是不包括最大的那几项,比如WebAppClassLoader,这个对象肯定大,但是这是看不出什么信息的
记一次OOM的分析
找到一个比较大的项,发现这是mybatis当中的类,这时候大概能想到应该是查询数据库时一次性查了大量的数据,我们继续往下看
记一次OOM的分析
发现确实如此,大量的ErpStaInfo对象存在,那这时候就该看看包路径是mybaits的那些类了,为了找到SQL语句,参数,以及mapperId等这些信息
记一次OOM的分析
可以看到这里已经找到对应的mapper了
记一次OOM的分析
这里找到了SQL和参数信息,选中bound sql右键go into:
记一次OOM的分析
选中sql右键copy->value可以复制SQL语句,参数也可以继续右键go into查看,sql语句,参数,mapperId这些信息都已经拿到,到这里我们基本已经定位到代码位置了,剩下的看代码逻辑找到原因就行了。

分析疑点2

按同样的思路来,这个就比较简单了,为了节省篇幅,这里只截图重要的部分
记一次OOM的分析
这里只找到了SQL语句和参数,没有mapperId,但是发现SQL语句和疑点1是一样的,其实就没必要继续分析了。

分析疑点3

堆中存在大量的字符串对象,这应该属于正常现象,所以没必要分析。

总结

通过这次的OOM分析,算是初步掌握了OOM分析的技能,但是还有更多的分析技能待学习,比如强大的OQL,掌握OQL绝对可以让你的分析能力上升到一个新的高度,甚至都不用mat这样的分析工具就能得到自己想要的信息,有时间再补一篇OQL的学习笔记吧,继续加油。
虽然这次OOM只是在测试环境,不怎么严重,但是一方面可以排除隐患,另一方面锻炼自己的事故分析能力,还是挺不错的。