跳到主要内容

OOM内存溢出问题排查

问题复现

Main类中定义了一个大小为 1M 的字节数组buffer。在main方法中,创建了一个ArrayList来存储Main对象。

通过一个无限循环,不断向列表中添加Main对象,直到发生内存溢出异常。

/**
* OOM溢出测试 -Xms16m -Xmx16m -XX:+HeapDumpOnOutOfMemoryError
* 说明:-Xms16m -Xmx16m 设置堆内存大小为16M,-XX:+HeapDumpOnOutOfMemoryError 当发生OOM时,自动生成dump文件
*/
public class Main {
// 初始化一个1M大小的数组
byte[] buffer = new byte[1024 * 1024];

public static void main(String[] args) {
List<Object> list = new ArrayList<>();
int count = 0;
try {
while (true) {
list.add(new Main());
count++;
}
} catch (Exception e) {
System.out.println("count = " + count);
e.printStackTrace();
}
}
}

添加启动参数:

image-20240902110303949

通过设置-Xms16m -Xmx16m参数,将堆内存大小设置为 16M;通过-XX:+HeapDumpOnOutOfMemoryError参数,当发生 OOM 时,会自动生成 dump 文件,以便后续分析内存溢出的原因。

此时运行报错,并生成了一个dump文件:

image-20240902110337087

问题分析

我们使用JProfile打开这个dump文件,也就是hprof后缀。

在运行中产生了实例数

image-20240902110549373

产生的一些大对象:

image-20240902110615780

可以看到就是因为我们不断的往这个List里面塞大数据,导致内存溢出

image-20240902110703545

在现场转储中,可以看到是出现了什么问题,以及是哪一行有问题

image-20240902110844899