Memory Analyzer :一款很强大的内存分析工具。
下载地址:https://www.eclipse.org/mat/downloads.php
1.首先弄个内存泄漏的场景
/** * ThreadLocal误用,模拟并发内存泄漏场景 * 可把JVM option -xmx设置小一些,例如800m,方便触发mmo */ @RequestMapping(value = "/test0") public String test0(HttpServletRequest request) { ThreadLocal<Byte[]> localVariable = new ThreadLocal<Byte[]>(); localVariable.set(new Byte[4096*1024]);// 为线程添加变量 return "success"; }通过ab工具,或者jmeter模拟多线程并发访问该接口,稍等一会。配合步骤1,就能拿到oom dump
2. 生成dump hprof内存快照文件,主要有两种方法
1)运行程序前添加JVM OPTION -Xms400m -Xmx800m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./tmp/heapdump.hprof -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:./tmp/heapTest.log
其中这两句才是关键产生dump设置 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./tmp/heapdump.hprof
2) 通过jmap命令,使运行程序生成dump快照 命令:jmap -dump:format=b,file=heapdump.hprof [pid]
3.通过MAT,打开hprof文件
总览界面如下:
图中圈红的部分,是最常用的功能,分别为leak Suspects、Histogram、Dominator Tree。
常用先看下leak Suspects,问题挺大概率出现在see stacktrace里面
MAT排查问题还是挺精准的
可能会有疑问,总览饼图里对象占用内存似乎不足800m(堆最大分配内存),但其实是因为并发速度快,导致频繁触发Full GC后把不可达对象的byte数组回收掉了,所以饼图看到当前内存占用并不高。可以检查Histogram或者Unreachable Objects Histogram
可以看到byte[]占用了异常巨大的内存。
ps:也可以使用jdk自带工具,jvisualvm打开hprof查看。