📜  java.lang.OutOfMemoryError:无法分配 345067788 字节分配,11479504 可用字节和 111MB 直到 OOM (1)

📅  最后修改于: 2023-12-03 15:01:35.239000             🧑  作者: Mango

Java.lang.OutOfMemoryError: Unable to allocate 345067788 bytes allocating, 11479504 available bytes and 111MB until OOM

如果你曾经编写过 Java 程序,那么你可能已经遇到过内存不足的情况。一旦 Java 程序用光了 JVM 堆中的所有内存,就会抛出 OutOfMemoryError 异常。这个异常告诉你,JVM 没有足够的内存来分配新的对象。

当出现以下错误时,就会抛出无法分配 345067788 字节的 OutOfMemoryError:

java.lang.OutOfMemoryError: Unable to allocate 345067788 bytes allocating, 11479504 available bytes and 111MB until OOM

这个错误告诉你,JVM 正在尝试分配 345067788 字节(大约 329MB)的内存,但只有 11479504 字节(大约 11MB)的空闲内存可供使用,而且在 JVM 用完这些内存之前仅剩下 111MB 的空闲内存。

为什么出现这个错误?

Java 程序使用 JVM 堆来存储对象。JVM 堆由一些连续的内存块组成。当 Java 程序创建新的对象时,JVM 会在堆中查找足够大的连续空间来存储它。如果没有足够的连续空间来存储对象,那么就会抛出 OutOfMemoryError。

OutOfMemoryError 通常是由以下原因之一导致的:

  • 程序请求超过实际可用的内存(例如,试图分配一个非常大的数组)

  • 程序存在内存泄漏(即程序无法释放不再使用的对象)

如何解决 OutOfMemoryError?

要解决 OutOfMemoryError,你需要了解你的程序到底使用了多少内存,以及内存是如何分配和使用的。以下是一些有用的技巧:

  • 使用 jmap 工具来获取 JVM 中的内存映像。jmap 命令可以生成一个内存快照,让你可以分析其中的对象和类。

  • 使用 jconsole 工具来监控 JVM 的内存使用情况。jconsole 可以显示程序的内存使用情况以及活动线程数。

  • 使用 HeapDumpOnOutOfMemoryError 选项来生成堆转储文件。当 JVM 抛出 OutOfMemoryError 时,该选项会自动将所有对象的详细信息写入一个转储文件中,让你可以分析内存泄漏问题。

  • 检查代码中是否存在内存泄漏。确保程序释放不再使用的对象,避免创建过多的对象和使用静态变量。

  • 调整 JVM 堆大小。如果使用的内存量高于 JVM 堆的大小,那么可以尝试增加 JVM 堆的大小,以便 JVM 有更多的内存可用来分配对象。

代码片段

以下是一个尝试分配大量内存的示例程序,它可能会导致 OutOfMemoryError:

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

public class MemoryLeaker {

    public static void main(String[] args) {
        List<byte[]> list = new ArrayList<>();
        while(true) {
            byte[] bytes = new byte[1024*1024*100]; //分配100MB内存
            list.add(bytes);
        }
    }
}

在这个程序中,我们创建了一个 ArrayList 对象来存储 100MB 的字节数组。然后,我们使用一个无限循环将这些字节数组添加到列表中。由于程序不会释放不再使用的字节数组,所以它将耗尽 JVM 堆的所有内存并最终导致 OutOfMemoryError。