一、下载dump文件。
需联系运维同事获取dump文件。dump文件的生成,需在jvm启动时通过添加启动参数:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=。因此直接到设置的目录文件下下载下来即可。后缀名一般为hprof。有些为dump后缀,改为hprof一样是可用的。
二、下载MAT工具。
本文分析oom文件需要借助MAT工具。MAT全名是Memory Analyzer,即分析JVM内存的工具。MAT实际是一个eclipse插件,在使用时还需下载eclipse.下载时可到这个地址下载:http://www.eclipse.org/mat/downloads.php,这里已经把MAT和eclipse都集成到一起了,所以很方便使用,推荐下载。
三、打开dump文件
打开eclipse后,直接将hprof文件拖到eclipse的工作区中。eclipse会自动打开这个文件,大约花费2到3分钟的时间,请耐心等待。打开后会看到下图所示的一个分析视图概览:饼状图显示的是内存中各对象的内存占比,最大的那块就是内存中占用空间最大的对象,把指标移到上面可以看出具体是哪个对象。但是因为我们自定义类大都使用包装类,比如String,Interger,故这里最大的对象,一般也是这些包装类,因此一般来说此图分析用途不大。
四、分析dump文件
1、找到上图Actions标签栏下的Dominator Tree
这个是我们本次分析的重点。dominator tree翻译是支配树,通过它能够找到对象之间的依赖关系。如下图所示。打开时就已经按照占用内存大小对对象进行了排序。排在最前面的就是占用内存最大的对象,这里实际就是上面饼状图的另一种表示。
2、找到org.apache.tomcat.util.threads.TaskThread
从过往分析的几个oom文件来看,TaskThread这个对象基本都是排前面几个的,因此比较好找。然后右键找到java Basics → Thread Details,如下图所示
3、查看TaskThread对象的线程栈
这里为啥找TaskThread对象,个人想法是,每个请求进来都是通过一个线程来进行处理的,故后续业务逻辑生成的对象多少会跟此对象有关联,因此可以把这个对象理解为业务处理的源头,通过分析它的线程栈,就可以找到出问题的方法。如下图所示,我们公司的代码都是com.to8to的前缀,根据这个应该很快就能找到我们要找的接口,这个接口就是产生大量对象的有问题的接口。接下来就需要结合具体业务进一步分析。