使用JvisualVM排查OOM

1 测试环境

使用JDK1.8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package jvm.oom;

import java.util.ArrayList;

public class TestOOM {
static class OOMObject {
private String content;

public OOMObject(String content) {
this.content = content;
}
}

public static void main(String[] args) {
ArrayList<OOMObject> list = new ArrayList<>();
int a = 1;
while (true) {
list.add(new OOMObject(String.valueOf(a ++)));
}
}
}

配置JVM参数:

1
2
3
4
-Xms2m	// JVM启动时堆内存的初始化大小
-Xmx4m // 设置堆内存最大值
-XX:+HeapDumpOnOutOfMemoryError // 表示出现OOM异常后,生成堆快照hprof文件
-XX:HeapDumpPath=d:\jvmtest // 设置堆快照hprof文件存储的位置

2 运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
java.lang.OutOfMemoryError: Java heap space
Dumping heap to d:\jvmtest ...
Unable to create d:\jvmtest: File exists
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:261)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
at java.util.ArrayList.add(ArrayList.java:458)
at jvm.oom.TestOOM.main(TestOOM.java:18)

Process finished with exit code 1

3 使用jvisualVM排查

  1. 使用CMD启动

    image-20220228183830553

  2. 装入生成的hprof文件

    image-20220228183924366

  3. 发现已经提示我们出现了OOM异常

    image-20220228183958367

  4. 发现是17行出现OOM

    image-20220228184054505

  5. 查看ArrarList

    image-20220228184145955

  6. 发现元素个数达到三万多,并且都是OOMObject对象

    image-20220228184145955

  7. 打开类视图,发现OOMObject对象确实占用了大量堆内存

    image-20220228184549443

通过以上分析,就可以大概知道是过多无法回收的OOMObject对象,导致了OOM

4 总结

  1. 生成堆转储快照dump文件(或者称hprof文件);
  2. 利用相关工具分析堆转储快照
  3. 在线程快照(堆转储上的线程)中定位到发生OOM的线程和代码位置
  4. 综合分析线程快照里提示的本地变量信息及类视图中的实例占比,找出导致OOM的实体类型

使用JvisualVM排查OOM
https://2w1nd.github.io/2022/02/28/JVM/使用JvisualVM排查OOM/
作者
w1nd
发布于
2022年2月28日
许可协议