记录 Memory Anallyzer Tool 相关概念与使用。
1. 名词概念解释
1.1 Shallow heap && Retained Heap
shallow是浅的意思,比如,一个ArrayList的浅占用仅仅是size,elementData[],modCount三个成员对象16个字节,加上引用8个字节,总共是24个字节。但是elementData才是冰山下的大头。retained直译是保留的意思,指的是某个对象所持有的所有对象(直接和间接)。某种意义上来说,reatined heap才是我们更加关注的对象。
1.2 Dominator Tree
Dominator Tree就是对象关系树,一个对象的所有子支配树对象,就是上面所说的retained heap。
1.3 Path to GC Roots
通过分析gc roots可以确定某些对象无法回收的原因。
1.4 Outgoing references && Incoming references
目标对象x,如果要查询x引用了谁,那么就是前者,如果要看x被谁引用,那么就是后者。
1.5 Garbage Collection Roots
GC Roots是一个能被GC Roots是一个能被堆访问到的对象,下面是几种GC Roots:
堆访问到的对象,下面是几种GC Roots:
- System Classes 系统加载的类
- JNI Local native 代码的本地栈帧
- JNI Global
- Thread Block 被一个活跃中的线程引用的对象
- Busy Monitor 锁
- Java Local 本地栈帧变量
- Native Stack native代码的本地栈帧
- Finalizable 正在等待执行finalize()方法的队列
2. 界面常用操作
打开一个dump下的堆内存界面如上,3819.heapdump下的8个图标分别含义分别如下:
- open overview panel 打开概述界面,图片里的就是概述界面。
- create a histogram from an arbitrary set of objects 打开对象统计界面
- open dominator tree for entire heap 打开对象关系树状图(类似于tree命令)
- open object query language studio 执行OQL查询
- show thread stack 展示线程堆栈
- run expert system test 运行自动检测内存泄漏等功能
- open query browser 打开查询界面,查询某个对象的被引用,引用对象等,必须指定一个对象
- find object by address 通过一个内存地址查询对象
3. Overview页面操作
当我们拿到一个heapdump并导入堆栈的时候,确保我们的内存大于heapdump文件,并且检查一下MemoryAnalyzer.ini文件,确保最大堆内存大于我们的heapdump文件。
解析完heapdump,直接打开overview,会有步骤建议如下:
3.1 actions
- Histogram:会打开所有的对象统计,可以按对象数量,shallow memory, retained memory排序
- Dminator Tree:直接展示支配树,一样可以按上面的几个条件排序
- Top Consumers:直接查看最耗费内存(retained heap)的的对象
- Duplicate Classes:检测重复加载的Class
3.2 reports
- Leak Suspects:泄漏检测,运行这个选项直接会给出可能的内存泄漏点
- Top Components:分析占用内存最高的的组件
4. Object Query Language
OQL语法类似SQL,下面是基本语法:
1 | SELECT * |
举个栗子,访问ArrayList中数组长度大于等于5的对象和他的所有持有的引用:
1 | SELECT as retained set * |
select如果加上AS RETAINED SET,将查询所有持有的引用。
from可以是objectAddress,objectId,className,或者是子查询的结果。
如果是一个对象的field,直接通过.的方式即可访问,使用.@访问MAT构建的JavaBean属性,这些属性如下:
属性名 | 属性含义 |
---|---|
objectId | 对象id |
objectAddress | 地址id |
clazz | class对象 |
usedHeapSize | 浅堆 |
retainedHeapSize | 保留堆 |
displayName | 类名 + 地址名 |
classLoaderIds | loaderId |
length | 数组的长度 |
valueArray | primitive数组的内容 .@valueArray[index] |
referenceArray | 引用数组的内容,使用方式同上 |
还有一些复杂的用法还不是很清楚,待探索。另外,上述所有的参考资料,可以直接从Memory Analyzer的Help->Help contents里面的文档查看,或者浏览器直接访问参考资料里的地址。