https://user.qzone.qq.com/731573705/blog/1436389384
Eclipse Memory Analyzer(MAT)使用
平时开发、测试过程中,有时会遇到OutOfMemoryError,Java堆溢出了,这表明程序有严重的问题,我们需要找出造成OutOfMemoryError原因。
一般有两种情况:
1、内存泄露,对象已经死了,无法通过垃圾收集器进行自动回收,通过找出泄露的代码位置和原因,才好确定解决方案;
2、内存溢出,内存中的对象都还必须存活着,这说明Java堆分配空间不足,检查堆设置大小(-Xmx与-Xms),检查代码是否存在对象生命周期太长、持有状态时间过长的情况。
以上是处理Java堆问题的思路,具体是怎么进行分析,这里介绍使用Eclipse Memory Analyzer tool(MAT)工具分析的过程。
常见OutOfMemoryError
java.lang.OutOfMemoryError:Java heap space
Java虚拟机堆里面已经没有更多的空间了。你正准备创建一个新的对象,但是这个要创建的对象需要的内存已经超过了虚拟机所剩的了。虚拟机会尝试通过full GC来回收内存,如果不行的话,就会抛出这个信息(可以通过-Xmx参数增加堆的大小来解决),如果不行,还是要找到出现问题的原因
java.lang.OutOfMemoryError:PermGen space
和第一个现象差不多,不过这里准备分配内存的空间是持久代。同样的,空间已经不够了,(增加了-XX:MaxPermSize这个参数的值,问题通常就解决了)
java.lang.OutOfMemoryError: GC overhead limit exceeded
这个问题有点特殊。这里没有提示说堆还是持久代有问题,虚拟机只是说程序花在垃圾回收上的时间太多了,却没有什么见效。默认的话,如果98%的时间都花在GC上并且回收了才不到2%的空间的话,虚拟机才会抛这个异常。
以上三种错误覆盖了98%以上的场景
java.lang.OutOfMemoryError: unable to create new nativethread
如果虚拟机正在请求操作系统创建一个本地线程,而操作系统无法创建的时候,你会收到这个报错信息。
java.lang.OutOfMemoryError:nativeGetNewTLA
指当虚拟机不能分配新的线程本地空间(Thread Local Area)的时候错误信息。这个异常只有在jRockit虚拟机时才会碰到。线程本地空间是多线程程序里面为了更有效的进行内存分配而建立的缓存。每一个线程都有一份自己的缓存,当这个线程要创建对象的时候,就在这上面分配。如果你有很多线程同时并发,又要创建大量的对象,可能会出现这个问题,这种情况下你可以调整一下-XXtlaSize这个参数
java.lang.OutOfMemoryError:Requested array size exceeds VM limit
当创建一个超过虚拟机允许的大小的数组时,这条错误就会出现
java.lang.OutOfMemoryError:request bytes for . Out of swap space
这个错误是当虚拟机向本地操作系统申请内存失败时抛出的。这个和用完了堆或者持久化中的内存的情况有些不同。这个错误通常是在程序已经逼*台限制的时候产生的。这个信息告诉你可能已经用光了物理内存以及虚拟内存了。
二、MAT使用
1、Mat插件安装
1)下载Mat ,Mat下载地址:http://www.eclipse.org/mat/
2)解压下载包:放到eclipse或myeclipse安装目录的dropins目录下
3)启动eclipse或myeclipse,打开window - > open perspective,看到Memory Analysis证明安装成功
也可以使用其它方法进行安装,不一一说明
2、生成dump文件
首前制造一条内存泄漏的用例,执行使程序报OutOfMemoryError
# ps -ef | grep java
# jmap -dump:live,format=b,file=mpfile1309
3、使用mat分析
启动eclipse或myeclipse,打开file - > Open heap dump,在弹出的对话框选择生成的dump文件(mpfile)打开heapDumps文件,就可以看到MAT给出了overview page
结果查看:
1.Histogram可以列出内存中的对象,对象的个数以及大小。
2. Dominator Tree可以列出那个线程,以及线程下面的那些对象占用的空间。
3.Top consumers通过图形列出最大的object。
4.Leak Suspects通过MA自动分析泄漏的原因。
分析:
Histogram如下图:
Objects:类的对象的数量;
Shallow size:就是对象本身占用内存的大小,不包含对其他对象的引用,也就是对象头加成员变量(不是成员变量的值)的总和;
Retained size:是该对象自己的shallow size,加上从该对象能直接或间接访问到对象的shallow size之和。换句话说,retained size是该对象被GC之后所能回收到内存的总和。
我们发现cn.test.TestBean类的对象占用了很多空间。
DominatorTree如下图:
我们发现cn.test.TestMain-java.util.arraylist-java.lang.object用了很多空间
Top consumers如下图:
这里显示了内存中最大的对象有哪些,他们对应的类是哪些,类加载器classloader是哪些。
有些时候,我们在这里就可以看到代码泄露的位置。
Leak Suspects如下图:
该图深色区域被怀疑有内存泄漏,深色区域就占了69.1%。后面的描述,告诉我们怀疑问题出在java.lang.object中。所以,MAT通过简单的报告就说明了问题所在。
通过Leak Suspects的Problem Suspect 1点击【Details】
从详细内容中我明可以明确的查出是cn.test.TestBean类的对象有问题,内存溢出
以上是通过MAT分析Tomcat应用程序,找到内存泄露的原因,还有许多不足之处,希望大家多多指教