一、可能产生内存泄露的地方

在进行排查 Java 的内存泄漏问题之前,首先我们要知道哪里可能会产生内存泄漏,我们来看看下面这张图:

在这里插入图片描述

在运行时数据区中,有三个地方可能会导致内存溢出或者内存泄漏:

  1. JVM Stacks 虚拟机栈: 报错是 StackOverFlowError,一般指递归造成的问题。
  2. Method Area/MetaSpace 方法区/元空间: OutOfMemoryError: Metaspace,一般指动态加载的类太多了。
  3. Heap 堆空间: 报错最常见的,报错是 OutOfMemoryError: java heap space,面试官一般主要关心的也是堆空间内存泄漏的问题,比如一些比较大的对象,一直存活,一直没有被垃圾回收器回收,这个就有可能会导致内存泄露的问题。

二、复现堆内存泄漏

接下来我们演示一下 Heap 堆空间 内存溢出的情况,代码如下:

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    while (true) {
        list.add("北京");
    }
}

这段代码比较简单,就是创建了一个 List,然后不断地向 List 中添加数据。在启动前,为了能够快速的看到我们的测试结果,我们需要添加一个 VM 参数 -Xmx10m,限制最大堆内存为10M:

这时候再去执行代码,报错如下:

  • java.lang.OutOfMemoryError: Java heap space

到目前为止,我们已经成功复现了堆内存泄漏的问题。


三、如何排查堆内存问题?

我们目前是在 IDEA 中进行了堆内存溢出的演示,从控制台可以清楚地看到报错的信息,也提示了具体哪一行代码可能导致内存溢出,我们只要找到这一行代码进行修复就可以了。但是我们的项目一般都是部署在服务器上的,这样的话该怎么排查呢?

举个例子,如下图所示:

比如说我们在服务器中部署了这些服务,这里面的每个微服务都有可能导致内存溢出,严重的话项目可能根本就没有启动起来,或者项目运行一段时间之后宕机了。这些都是有可能的,那这些问题应该怎么排查呢?

针对生产内存溢出问题的排查步骤:

  1. 获取堆内存快照 dump;
  2. 使用 Visual VM 去分析 dump 文件。
  3. 通过查看堆信息的情况,定位内存溢出问题。

下面我们就按照这个步骤去进行排查。

3.1 获取对内存快照 dump

  • 如果项目还在运行,我们可以通过 jmap 命令打印它的内存快照 dump。命令如下:
jmap -dump:format=b,file=heap.hprof <pid>

补充: Dump 文件是 Java 进程的内存镜像。可以把程序的执行状态通过调试器保存到 dump文件中。

  • 如果项目已经闪退了,我们可以通过在启动命令中添加 vm 参数的方式来生成 dump 文件。命令如下:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/home/app/dumps

举个例子,我们还是使用上面那段代码:

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    while (true) {
        list.add("北京");
    }
}

只是这次启动的时候,我们要在启动参数中加入我们上面提到的参数:

设置好 vm 参数之后,再次执行代码,结果如下:

可以看到,堆内存快照dump文件已经被存储下来了:

在这里插入图片描述

3.2 使用 Visual VM 去分析 dump 文件

接下来,我们来到 JAVA_HOME/bin/ 目录下,找到 Visual VM:

在这里插入图片描述

双击打开之后,点击 文件 -> 装入

在这里插入图片描述

首先切换文件类型为:堆 Dump,选择我们刚才导出的 dump 文件,打开。

打开之后,就可以看到导出的堆内存情况了:

在这里插入图片描述

3.3 定位内存溢出问题

从上图中可以看到,Visual VM 已经明确告诉我们程序发生了 OOM 异常,发生在 main 线程中,我们点击 main 就可以看到 main 线程的信息:

在这里插入图片描述

从上图中可以看出,这里已经明确提示了具体是哪一行代码出现了错误。我们只要在代码中找到这一行,检查一下这一行代码的上下文,就可以找到并解决掉问题。

以上就是 Java 内存泄漏的排查思路了。

整理完毕,完结撒花~🌻

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐