情景:周五的时候,运维突然发现平时正常运行的服务重启了,同时查看了日志,发现有gc outOfMemory的日志,并且生成了当时的dump文件,通知我有时间的话排查下问题,是什么导致重启的,平时都没有这种情况;

刚好这周事情少,有点时间,就开始着手排查;
1.准备mat软件
首先从网上下载下mat软件,我这里用的是mac OS版本的,安装完后,用命令行打开,具体方式可以自行百度,同时从ftp上下载log文件以及dump文件
mac OS mat.app 下载链接:
链接: https://pan.baidu.com/s/1nMa_XqK_DPtd6GPz5PioOg 密码: 7aur

可以通过上面的file->open file,选择自己的dump文件路径,注意dump文件的格式是有要求的,否则打不开,我这里用的都是*.bin结尾的;
2.使用Leak Suspects Report初步分析
打开文件,后会跳出下面弹窗

选择Leak Suspects Report然后点击finish,等待软件一段时间的解析后会出现以下界面:

咱们着重看自己相关的类,翻到最下面可以看到e,也就是Problem Suspect5,点击Details,出现以下界面

由上面图片可以看到是ibatis相关操作导致的,百度查询下class org.apache.ibatis.executor.result.DefaultResultHandler导致的相关问题,发现它的作用是将statement执行后的结果,转换成对象列表;
3.分析该对象是否存在强引用
如图:


点击查看其GC ROOT对象是由tomcat引用,由此可知,肯定是某一个接口导致查询数据库的数据量过大,然后最终导致outOfMemory;
4.定位到最终问题,即是哪条sql导致
在当前页面点击按钮

出现以下界面

这是根据Retained Heap 进行从大到小排序后的结果;
从大到小,逐个打开其中的内容,将里面的sql内容复制出来,然后去线上数据仓库,进行count查询,查看具体返回条数,这里我看到http-nio-8018-exec-2 线程中的sql执行,查询到了14W条数据,定位到是这条sql引起的outOfMemory;
5.定位具体代码
有了sql就好办了,在项目中查询到相关sql,以及引用之处,发现一共有三个接口使用了,该方法,根据报错时间范围和接口名去kibina中查询相关接口的请求入参,发现就是其中一个接口的入餐没有传入所需参数,导致查询出14W条数据,最终产生了outOfMemory;
具体解决方案的话就视业务而定了,最简单的方案就是如果该参数为空则返回参数异常;
网友评论