前言
前几天在公司服务器查看日志的时候无意间发现项目配置的OOM Dump
路径上生成了一个文件,发现就是最近生成的文件。好奇之下笔者将该文件拉到本地准备开始定位问题。
问题定位
话不多说,直接利用MAT
工具对该文件进行分析。
通过上图可以发现是sql返回的一个结果集占用了大量的内存,接近1.5G!但是这里还看不出来到底是哪块业务代码造成返回这么大的数据集。再看MAT
的一个系统报告,它可以帮你预测出这个内存快照可能出现问题并且同时给出线程快照。
接下来我们找出是哪个线程出的问题,如下图:
既然找到造成OOM的线程了,那就直接查看堆栈,就可以定位到具体的业务代码了!笔者这边发现mybatis查询的时候根据对应的条件是否存在进行拼接查询,由于该接口少传了一个参数,导致数据库进行全表查询,然后……就造成眼前的悲剧了。
优化
1、进行请求参数的必传校验。(该参数确实是必传的,但是业务端没有做校验)。
2、查看代码发现这条sql查的是一个对象,也就是一个结果集,但是sql结尾中并没有加limit 1
条件,所以为了防止匹配多条结果集,加上limit 1
会更优。
总结
本次问题是经典的内存溢出问题,这类问题一般都是使用MAT
工具进行问题定位并分析。首先找到占用内存大的那个对象,然后从线程堆栈中定位到具体的业务代码。