什么是 OutOfMemoryError 以及如何在 Java 中查找 OOM 的根本原因?

javaobject oriented programmingprogramming

当 JVM 没有足够的可用内存进行分配时,JVM 会抛出 OutOfMemoryError OutOfMemoryError 属于 Exception  类层次结构中的 E错误类别

要生成 OutOfMemoryError

  • 我们将分配一大块内存,这将耗尽堆内存存储
  • 我们将继续分配内存,直到达到点,当 JVM 没有足够的内存可分配时,将抛出 OutOfMemoryError 
  • 一旦我们捕获 OutOfMemory  错误,我们就可以记录错误。

示例

public class OutOfMemoryErrorDemo {
   public static void main(String[] args) throws Exception {
      int dummyArraySize = 15;
      System.out.println("Max JVM memory: " + Runtime.getRuntime().maxMemory());
      long memoryConsumed = 0;
      try {
         long[] memoryAllocated = null;
         for(int loop = 0; loop < Integer.MAX_VALUE; loop++) {
            memoryAllocated = new long[dummyArraySize];
            memoryAllocated[0] = 0;
            memoryConsumed += dummyArraySize * Long.SIZE;
            System.out.println("到目前为止已消耗的内存:" + memoryConsumed);
            dummyArraySize *= dummyArraySize * 2;
            Thread.sleep(500);
         }
      } catch (OutOfMemoryError outofMemory) {
         System.out.println("Catching out of memory error");
         //记录信息,以便我们生成统计数据
         throw outofMemory;
      }
   }
}

输出

最大 JVM 内存:119537664
迄今为止消耗的内存:960
迄今为止消耗的内存:29760
迄今为止消耗的内存:25949760
捕获内存不足错误
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at OutOfMemoryErrorDemo.main(OutOfMemoryErrorDemo.java:9)

查找 OOM 根本原因的步骤

步骤 1:在 OutOfMemoryError 上生成堆转储

使用 VM 参数 -XX:+HeapDumpOnOutOfMemoryError 启动应用程序。这将告诉 JVM 在发生 OOM 时生成 堆转储

$ java -XX:+HeapDumpOnOutOfMemoryError ...

步骤 2:重现问题

如果我们无法在开发环境重现问题,我们可能必须使用生产环境。当我们重现问题并且应用程序抛出 OOM 时,它将生成一个堆转储文件。

步骤 3:使用堆转储文件调查问题

使用 VisualVM 读取堆转储文件并诊断问题。 VisualVM  是一个位于 JDK_HOME/bin/jvisualvm 中的程序。堆转储文件 包含有关应用程序内存使用情况的所有信息。


相关文章