Memory Analyzer 是什么
Memory Analyzer(MAT)是由 eclipse 提供的一款可视化 java 堆分析器,可以快速帮你查找内存泄漏并减少内存消耗,它提供了可视化的报告并可以查看堆文件中各个对象的信息。官网下载链接
什么时候用 MAT
当线上的某个 service/微服务老莫名其妙的崩掉或者出现莫名问题,当你需要对不熟悉的代码进行调优,当内存溢出/泄漏且代码量巨大的时候。因为 MAT 的可视化,你很容易就能把堆文件里面对应的大对象找出来,随之可以快速的定位大对象对应的代码处进行查看。
MAT 实践
1) 内存溢出
/**
* 测试内存溢出
*/
public class TestHeapSpace {
public static void main(String[] args) throws Exception{
getLines("/Users/yangjunwei/data/test/HNP_StatsFootNot.csv").forEach(x-> System.out.println(x));
}
/**
* 返回文件的内容 * @param file
* @return
* @throws Exception
*/
private static List getLines(String file) throws Exception{
BufferedReader reader = null;
List list = new ArrayList<>();
try{
reader = new BufferedReader(new FileReader(new File(file)));
String tmp =null;
while ((tmp = reader.readLine()) != null){
list.add(tmp);
}
}finally {
if( reader != null ){
reader.close();
}
}
return list;
}
}
上面是一个读取文件内容的例子,乍一看问题不大,但文件内容过多,执行内存不是太大的情况下会发生什么?
ll -h /Users/yangjunwei/data/test/HNP_StatsFootNot.csv
22M 1 25 13:06 /Users/yangjunwei/data/test/HNP_StatsFootNot.csv
// 模拟内存溢出,限定该程序最大堆内存为10M,因为文件内容为22M,10M必然加载不了22M的文本信息,所以就发生了内存溢出异常并导出了堆文件(启动参数加了-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath)。
java -jar -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath='/Users/yangjunwei/data/test/head_outMemory.hprof' -Xmx10M yy_test_heap_outMemory.jar
java.lang.OutOfMemoryError: Java heap space
Dumping heap to /Users/yangjunwei/data/test/head_outMemory.hprof ...
Heap dump file created [10782477 bytes in 0.064 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Arrays.java:3664)
at java.lang.String.<init>(String.java:207)
at java.io.BufferedReader.readLine(BufferedReader.java:356)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.winasdaq.yy_test.TestHeapSpace.getLines(TestHeapSpace.java:32)
at com.winasdaq.yy_test.TestHeapSpace.main(TestHeapSpace.java:15)
ll -h /Users/yangjunwei/data/test/head_outMemory.hprof
10M 2 1 15:44 /Users/yangjunwei/data/test/head_outMemory.hpro
下来咱们就用 MAT 来分析一下这个 10M 的堆文件
1.1 打开要分析的堆文件
1.2 选择 LEAk REPORT
1.3 LEAk REPORT 的饼图(由这个饼图发现有一个问题,有一个大对象占了 8.7M 的内存)
1.4 揪出这个大对象
1.5 定位问题
发现那个大对象是一个 ArrayList,并占了百分之 97 的内存。这个对象的里面的记录正是文本的一行行记录。
2) 内存泄漏
如果上述代码申请了足够的内存且在一个 webservice 里面,把下面代码代码注释掉就会发生内存泄漏。
if( reader != null ){
reader.close();
}
当一个对象失去所有的引用的时候,在 GC 的时候,就可以将其回收,反之则不回收,因为 reader 里面加载了文件的内容还没有关闭,所以它不会被 GC 回收,一个泄漏不可怕,多次泄漏之后堆内存里面会存放大量的不能被 GC 回收的对象,最终会导致于把内存撑爆,发生内存溢出的情况。用 MAT 实践同样能定位到问题,这里就不做赘述。
堆文件导出
1)被动导出,上面测试内存溢出的范例中已有,启动参数加上(-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPat)即可,这种情况只是在内存溢出的时候才会被动导出堆文件
2)利用 jdk 的工具 jmap 把堆文件主动导出(openjdk 的话要另外安装 openjdk-devel 包)
$ ./jmap
Usage:
jmap [option] <pid>
(to connect to running process)
jmap [option] <executable <core>
(to connect to a core file)
jmap [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)
where <option> is one of:
<none> to print same info as Solaris pmap
-heap to print java heap summary
-histo[:live] to print histogram of java object heap; if the "live"
suboption is specified, only count live objects
-clstats to print class loader statistics
-finalizerinfo to print information on objects awaiting finalization
-dump:<dump-options> to dump java heap in hprof binary format
dump-options:
live dump only live objects; if not specified,
all objects in the heap are dumped.
format=b binary format
file=<file> dump heap to <file>
Example: jmap -dump:live,format=b,file=heap.bin <pid>
-F force. Use with -dump:<dump-options> <pid> or -histo
to force a heap dump or histogram when <pid> does not
respond. The "live" suboption is not supported
in this mode.
-h | -help to print this help message
-J<flag> to pass <flag> directly to the runtime system
先 ps -ef|grep java,把需要导出的 java 的 pid 找出来,然后通过 jmap 命令导出
// 导出pid为1151的堆文件,格式2进制,导出文件为/Users/yangjunwei/data/test/1151.hprof
./jmap -dump:format=b,file='/Users/yangjunwei/data/test/1151.hprof' 1151
Dumping heap to /Users/yangjunwei/data/test/1151.hprof ...
Heap dump file created
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于