2020年3月

使用说明

发生OOM的情况一般都是因为程序中存在大对象,如果大对象存在是合理的,则说明程序需要的内存不足够。
而jprofiler就是一款可以根据dump信息检查程序OOM异常的软件。

jprofiler安装

idea插件搜索jprofiler安装,并去jprofiler官网下载软件:https://www.ej-technologies.com/products/jprofiler/overview.html
OK

解决思路

第一步:把jvm内存调大

VM options:

// 按倍调整
-Xms2048m -Xmx2048m

运行程序观察,如果在大内存下运行依然存在OOM问题,则说明是程序代码出现了问题。

第二步:定位OOM代码

    1. 调整对应的vm参数并dump出异常。

      //把jvm内存调小,让程序提前OOM。
      -Xms1m -Xmx4m -XX:+HeapDumpOnOutOfMemoryError
    1. 运行程序生成线程执行信息文件
      使用了dump命令,当运行main方法后,除了在控制台输出Exception外还会在根项目路径下生成一个java_pid.hprof文件,里面保存了程序线程执行的内容。
    1. 使用jprofiler分析
      本地安装完成jprofiler软件后,可以直接双击打开项目根路径下的java_pidxx.hprof文件即可。
      我们需要关心的有:biggest objects和thread dump这两个主要信息。

biggest objects中我们可以知道项目存在哪些大对象,而从thread dump可以知道哪行代码发生了OOM(需要的就是这个)。

Dump命令可以捕获我们指定的error,只需要在-XX:指定即可。

例子

    1. 编写一个让内存溢出的main线程程序,并在设置jvm参数后运行

      /**
       * 设置堆内存溢出
       */
      public class OOMTest {
        public static void main(String[] args) {
         List list = new ArrayList<String>();
         int count = 0;
         try{
             while (true) {
                 list.add(new OOMTest());
                 count += 1;
             }
         } catch (Error error) {
             System.out.printf("count= "+ count);
         }
        }
      }

    1. 在edit configurations中设置vm参数

      -Xms1m -Xmx4m -XX:+HeapDumpOnOutOfMemoryError

    1. 运行程序,生成dump文件


可以看到count在while循环第106711次后发生了OOM,并生成了java_pid3652.hprof文件。

    1. jprofiler使用
      打开hprof文件后点击大对象可以看到一个很大的对象类型:ArrayList

点击thread dump后选择我们运行的main线程可以看到,oom溢出定位到第15行代码中。(的确是发生在第15行)

over

还可以使用-XX:+PrintGCDetails命令打印输出GC垃圾回收信息,查看gc回收的过程。