真到了需要分析堆内存的时候,感觉MAT还是目前最好用的工具。其它工具也涉及到一些内存分析的能力,比如VisualVM,但是在内存分析的功能方面,还是不如MAT全面。
用jmap命令来dump堆内存。网上看到的命令一般长这样:
jmap -dump:live,format=b,file=heap.hprof 12345
加了live参数,dump内存的时候是会引发一次full GC的,这个是一个需要避的小坑。也许你需要关心那些被回收掉的对象,但是这样dump出来的就没有那些对象了。
另外,就是MAT好像默认是自动过滤unreachable对象的。也就是说,即便是你在用jamp dump的时候没有加上live参数,等你用MAT打开dump文件的时候,那些对象也会被MAT过滤掉。在Settings里打开开关就好。
分析内存占用时,最常用的是Top Consumers和Dominator Tree这2个面板。Top Consumers快速定位top对象,Dominator Tree则是详细分析每个对象的占用情况。Dominator Tree面板上会显示2列:
- Shallow heap: 一个对象自身占据的内存空间大小,这个跟对象的布局有关系
- Retained Heap: 对象的Retained Set集合中所有对象的Shallow heap的总和
那Retained Set又是什么呢?就是当一个对象被垃圾回收的时候,会随之一起被回收掉的对象。简单可以理解成这个对象的成员变量。
如果你真的dump出来很大的文件,比如3个G这种的(再大的我没遇到过),可能你的mat会挂起半天打不开文件。这种情况可以试着调整配置文件看看。Mac上的配置文件路径:
/Applications/mat.app/Contents/Eclipse/MemoryAnalyzer.ini
就跟调JVM参数一样的,在配置文件的最后加上:
-Xms1024m
-Xmx8192m
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled
-XX:+CMSClassUnloadingEnabled
-XX:+UseCMSInitiatingOccupancyOnly
-Dorg.eclipse.swt.internal.carbon.smallFonts
-XstartOnFirstThread
在shell配置文件中加上一个alias,方便传入data参数:
alias mat="/Applications/mat.app/Contents/MacOS/MemoryAnalyzer -data ~/Work/mat &"
这样每次从shell终端输入mat就能启动它了