Eclipse Memory Analyzer是一个快速而功能丰富的Java堆分析器,可帮助您查找内存泄漏并减少内存消耗。
使用内存分析器分析数亿个对象的生产性堆转储,快速计算保留的对象大小,查看谁阻止垃圾收集器收集对象,运行报告以自动提取泄漏的嫌疑人。
Eclipse Memory Analyzer
安装
下载Eclipse并安装,下载地址:https://www.eclipse.org/downloads/。
在Eclipse help -> Eclipse Marketplace下搜索Memory.找到图中的软件,默认安装就可以。
测试代码
package org.fenixsoft.jvm.chapter2;
import java.util.ArrayList;
import java.util.List;
/**
* VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
*
* @author zzm
*/
public class HeapOOM {
static class OOMObject {
}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<OOMObject>();
while (true) {
list.add(new OOMObject());
}
}
}
VM options配置
-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:\test.hprof
HeapDumpOnOutOfMemoryError 内存溢出时dump文件保存在HeapDumpPath指定的位置,-XX:HeapDumpPath=/usr/local/tomcat 这样可以只指定保持的目录
-Xms20m 指定JVM初始内存为20m,-Xmx20m 指定JVM最大可用内存为20m
idea中异常信息打印:
org.fenixsoft.jvm.chapter2.HeapOOM
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid21692.hprof ...
Heap dump file created [28257710 bytes in 0.164 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:261)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
at java.util.ArrayList.add(ArrayList.java:458)
at org.fenixsoft.jvm.chapter2.HeapOOM.main(HeapOOM.java:20)
Process finished with exit code 1
分析
在Eclipse Memory Analyzer试图中,选择File -> Open Heap Dump
Overview页面
在窗口上方的位置可以看到 heapDump 的 size,以及类、对象和类加载器的数量。
在窗口中最醒目的饼图直观地显示了 dump 中最大的几个对象。鼠标光标划过饼图中代表某个对象的区块时可以在左侧 Inspector 窗口中看到对象的细节,在区块上点击鼠标左键可以通过菜单项钻取到关于其对应的对象更多的细节。
我们可以看到占用很大一部分内存的有几个深色的饼区,这些就可以当做我们稍后着重看的地方
这里看到最大的那个占用内存的对象,对象名称,Shallow Size也就是本身在堆内存中120B并不大,但是Retained Size有15.5M,说明这个大对象中包含的引用对象很多。
Histogram
点开Histogram,点击Shallow Heap或Retained Heap排序,可以看见前排占用大量空间的有哪些
- Shallow Heap浅堆:java对象占用的内存
- Retained Heap深堆:java对象及对象引用的类占用的内存 ,jvm gc回收时释放的内存
- Retained Heap深堆大于等于Shallow Heap浅堆
如果想看这个具体有哪些对象,可以点击这个右键->show objects by class -> by outgoing Reference
Incomming Reference 指的是引用当前对象的外部对象; Outgoing Reference 指的是当前对象引用的外部对象。
对象的 incomming reference 保证对象处于 alive 从而免于被垃圾回收掉。
Outgoing reference 则展示了对象的具体内容, 有助于我们发现对象的用处。
比如可以看到Object[]这个对象本身就很大,它的引用外部对象很小,说明它的内存主要是由于本身定义的过大引起的。
第二个对象就是由于引用外部对象过多引起的。
Dominator Tree
Dominator Tree 展示了 Heap Dump 中最大的几个对象。 如果 dominator tree 中对象的父节点被移除的话那么, 那么相应对象及其后代节点也面临被回收的状态。
如果想探究一个对象持有了哪些对象并使之处于 alive, Dominator Tree 会是个很有用的工具。 此外还可以在 Dominator Tree 上按照 classloader 或 package 进行分组, 从而简化分析的过程。
可以点击左边你的三角展开查看持有的alive对象。
Top Consumers
Top Consumer 与Override页类似,Top Consumer 页按照对象、类、 类加载器和包也分别提供了对应的类似图表信息
Leak Suspects
通过前面简单的了解,我们大致了解了什么地方的内存比较占用高,最后这个报告是Mat帮我们分析的可能怀疑内存泄露的地方
引用