《JVM第10课》内存溢出(OOM)排查过程-工具

时间:2024-11-13 09:07:06

工具有很多,比如 jvisualvm、JProfile、Eclipse Memory Analyzer等等,各有千秋。我们这里只演示jvisualvm的用法。

我们先创建一段代码,让它抛出OOM异常并自动导出内存快照:

package com.fanren;

import java.util.ArrayList;
import java.util.List;

public class Test1 {

    static List<Integer> list = new ArrayList<>();

    public static void main(String[] args) {
        for (int i = 0; i < 1000000; i++) {
            list.add(i+1);
        }
    }
}

然后配置启动类,配置堆内存为10m并且发生OOM时自动导出内存快照:

在这里插入图片描述

接着运行就会报错:

在这里插入图片描述

已经发生OOM异常并且导出了 java_pid25104.hprof 文件。

接下来我们就可以在工具中使用 java_pid25104.hprof 文件排查OOM的原因了。

1.jvisualvm

jvisualvm在JDK 6 Update 7版本后作为标准工具被引入,也就是说 jvisualvm 是 JDK 自带的,省的下载了。

我们在控制台输入 jvisualvm 即可打开该工具。

在这里插入图片描述

如上图,进来后如果本地有正在运行的 Java 进程,可以监控此进程,双击打开可以看到右侧也有类似于 jconsole 的监控界面。也可以在此界面执行垃圾回收或是导出(dump)当前堆的快照,非常方便。

jvisualvm 不仅可以监控正在运行的进程内存状况,也可以导入内存快照。只需点击左上角的“装入快照”,我们把刚刚导出的 java_pid25104.hprof 给装入进来后如下图:

在这里插入图片描述

“概要”视图里已经提示了发生OOM的线程,点击之后就可以看到报错的行号:

在这里插入图片描述

可以发现正是我们的问题代码所在的行。

如果通过报错行号找到的不是导致OOM的罪魁祸首,那么可以点击“类”视图:

在这里插入图片描述

“类”视图里按照内存大小倒序后可以看到,Integer 类型对象占用了最多的空间,我们双击此行进入到“实例数”视图。如下:

在这里插入图片描述

在这个视图里选中一个对象实例,就可以在右侧“引用”模块查看到引用该对象的类是 Test1。

这样的话就可以得出结论:内存溢出是 Test1 类里面的 Integer 对象过多导致的。

于是我们就可以排查代码写得是不是有问题了。