哈喽,大家好,本期这一系列,咱们聊一下发生OOM咱们应该怎么处理。
读者们可以去搬运工小胖——MAT工具下载地址里面下载Eclipse Memory Analyzer
工具。有兴趣的小伙伴可以搬运工小胖——使用Eclipse Memory Analyzer的技巧看一波lan大佬怎么分析的。资源先摆上来,方便大家的使用。
1. 生成dump文件
小胖采用的是idea
,毕竟网上Eclipse使用MAT的攻略蛮多的。首先要去配置JVM
参数。

-Xmx20m -Xms5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/b.dump
这里咱们说一下参数的含义。
-Xmx20m
最大堆的大小20m;
-Xms5m
最小堆的大小5m;
-XX:+HeapDumpOnOutOfMemoryError
可以让虚拟机在出现内存溢出时Dump出当前内存堆存储快照以便我们分析;
XX:HeapDumpPath=d:/b.dump
存放 dump
文件的地址。

书写测试类代码:
public class TestJVM {
static class OOMObject {
private String name;
public OOMObject(String name) {
this.name = name;
}
}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<>();
while (true) {
list.add(new OOMObject("小胖同学"));
}
}
}
运行代码,发现出现JVM异常:

2. 使用MAT加载dump日志
双击exe
文件,打开MAT文件:

点击File
——>Open Heap Dump...
——>选择生成的dump文件
(点击之后,要在下面文本框中搜索文件的)

3. 使用MAT分析dump文件
3.1 浅堆和保留堆的概念
首先,在这里,要引入两个概念:
Shallow Size( ['ʃæləʊ] 浅
):对象本身占用内存的大小,不包括它的引用对象。
针对非数组类型
对象,它的大小就是对象与他所有成员变量大小总和。
针对数组类型
的对象,它的大小就是数组元素对象的大小总和。
Retained Size( [rɪ'teɪned] 保留
):就是当前对象被GC后,从Heap上总共能释放掉的内存。不过,释放的时候还要排除被GC Roots直接或者间接引用的对象。

A对象的Retained Size
就是A对象的Shallow Size
大小。
B对象的Retained Size
就是A对象的Shallow Size
大小+C对象大小。
因为D对象是被GC直接引用,故不能释放。

我们可以看到main线程下,自身的内存Shallow Size
占用是120B,但是Retained Size
,GC后可释放的对象。几乎占满堆内存。
3.2 分析Dominator Tree
我们可以通过Dominator Tree['dɒmɪneɪtə] 支配者
菜单选项进行排查。Dominator Tree提供了一个列表。Dominator Tree:对象之间dominator关系树。如果从GC Root
到达Y的的所有path都经过X,那么我们称X dominates Y
,或者X是Y的Dominator
。

3.3 分析Histogram 柱状图
histogram ['hɪstəɡræm]
如果需要查询特性的某个类,我们可以在第一行输入类名或者关键词进行正则匹配查找。我们可以找到疑似内存泄露
的类。
比较重要的一点,选中疑似类,右键出来选中List Objects,得到的结果再右键选中"Paths to GC Roots",我们可以通过它快速找到GC ROOT,如果存在GC ROOT,它就不会被回收。

3.4 Path to GC Roots
查看一个对象到RC Roots
的引用链 通常在排查内存泄漏的时候,我们会选择exclude all phantom/weak/soft etc.references
,意思是查看排除虚引用/弱引用/软引用等的引用链,因为被虚引用/弱引用/软引用的对象可以直接被GC给回收,我们要看的就是某个对象否还存在Strong
引用链(在导出HeapDump之前要手动出发GC来保证),如果有,则说明存在内存泄漏,然后再去排查具体引用。

其它重要选项:
- List objects :
with incoming references
引用到该对象的对象
with outcoming references
被该对象引用的对象- Show objects by class :
incoming references 引用到该对象的对象
outcoming references 被该对象引用的对象
引用ListArray的对象with incoming references
:

ArrayList引用的对象with outcoming references

文章参考:https://bjyzxxds.iteye.com/blog/1532937
https://blog.csdn.net/Jin_Kwok/article/details/80326088
网友评论