JVM-如何定位线上OOM?

72 阅读2分钟

1. 什么是OOM?

OOM:内存溢出。

2. 造成OOM的原因有哪些?

1)一次性申请了太多的资源。如:一次性从数据库中,查询出过多的数据,导致内存溢出。
2)内存资源资源耗尽,没有得到释放。
3)本身分配的堆内存资源就不够。可以使用jmap -heap来进行查看

3. 如何定位OOM问题?

3.1. 运行的系统已经挂了

这种方式呢,我们在运行系统的时候,添加对应的参数: -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/logs,其中/home/logs为堆内存溢出的路径。 如下所示例子:

我们创建一个SpringBoot项目,在启动类中添加如下代码:

@SpringBootApplication
public class HeapDemoApplication {

    public static void main(String[] args) {

        SpringApplication.run(HeapDemoApplication.class, args);
        List<String> list = new ArrayList<>();
        while (true){
            list.add(UUID.randomUUID().toString());
        }
    }
}

创建一个随机的字符串,不断的往list集合中添加。 打包后,我们使用如下命令运行:

java -Xms10M -Xmx10M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./logs/ -jar heap-demo-0.0.1-SNAPSHOT.jar &

运行后,出现OOM:

去到对应的日志文件夹下面,可以看到对应的文件。

image.png

2.2. 系统运行中,但还未出现OOM的情况

  • 我们可以导出dump文件,jmap -dump:format=b,file=./log/liwei.hprof 进程ID
  • 或者是利用arthas工具。

这两种方式都可以。 这里我们先看第一种情况。

这种情况,我们在排查问题的时候,需要付出成倍的时候或者是更多的时间牌排查问题,为什么呢?

先上图:我们先让我们的程序跑起来:

image.png

然后我们使用命令:jmap -histo:live pid,pid指的是进程号。

image.png

image.png

我们就可以知道是哪一个类占用内存比较高,但是无法具体到哪一行,所以,需要花更多的时间来排查问题。

使用命令导出:jmap -dump:format=b,file=./log/liwei.hprof 进程ID。然后就可以想第一种方式一样,使用visualVM工具来查看。