背景
运维同学告知xx项目OOM了,丢给我一个dump文件,让我分析一下,xx项目线上堆内存大小512M,Jdk8。
工具
Eclipse Memory Analyzer(mat)
案例分析
启动工具后打开 File - Open Heap Dump,然后选择生成的Heap DUmp文件
如下图所示:
点击leak suspect(内存泄漏可疑点)
如下图所示:
英语是个二把刀的我大致猜测了一下应该是MySQL查询出太多行,导致结果集映射的时候积累了大量内存
点击detail,如图所示:
找到Shortest Paths To the Accumulation Point(到聚焦点的最短路径)可以看到
ResultSetImpl的保留堆大小为89,100,112KB,约84M,右键点击左下角sql--copy--value,拿
到test环境执行了一下,发现该sql能查出十几万的数据sql是做的in查询,in括号里面的条件有两
三百个,一个条件对应的结果大概有四五百条,服务之间是微服务调用,业务调用方的频繁调
用,导致内存溢出,找到问题点就好解决问题啦。
还可以通过查看thread overview查看线程概览,查看此时的线程调用情况也可以找到问题
点击如图所示两个齿轮一样的按钮:
可以看到,第一二两个线程的retained heap大小大概为几十兆,点击如果所示线程左侧的三
角符号,查看该线程栈调用情况,找到该项目的包名,如下图:
也可以找到当前线程执行的sql
Shallow Heap 和 Retained Heap 的区别
Shallow Size是对象本身占据的内存的大小,不包含其引用的对象。
Retained Size是当前对象大小+当前对象可直接或间接引用到的对象的大小总和。并且排除被GC Roots直接或者间接引用的对象
参考:
https://blog.csdn.net/a740169405/article/details/53610689
https://www.jianshu.com/p/c34af977ade1