java - 当内存不足引发 OutOfMemoryError 时会发生什么?

标签 java language-agnostic

我知道每个对象都需要堆内存,而堆栈上的每个原语/引用都需要堆栈内存。

当我尝试在堆上创建一个对象并且没有足够的内存来执行此操作时,JVM 会创建一个 java.lang.OutOfMemoryError在堆上扔给我。

隐含地,这意味着JVM在启动时保留了一些内存。

当这个保留的内存用完(它肯定会用完,阅读下面的讨论)并且 JVM 在堆上没有足够的内存来创建 java.lang.OutOfMemoryError 的实例时会发生什么? ?

它只是挂起吗?或者他会扔给我一个 null 因为没有内存来 new 一个 OOM 的实例?

try {
    Object o = new Object();
    // and operations which require memory (well.. that's like everything)
} catch (java.lang.OutOfMemoryError e) {
    // JVM had insufficient memory to create an instance of java.lang.OutOfMemoryError to throw to us
    // what next? hangs here, stuck forever?
    // or would the machine decide to throw us a "null" ? (since it doesn't have memory to throw us anything more useful than a null)
    e.printStackTrace(); // e.printStackTrace() requires memory too.. =X
}

==

为什么 JVM 不能预留足够的内存?

无论保留多少内存,如果 JVM 没有办法“回收”该内存,该内存仍有可能被用完:

try {
    Object o = new Object();
} catch (java.lang.OutOfMemoryError e) {
    // JVM had 100 units of "spare memory". 1 is used to create this OOM.
    try {
        e.printStackTrace();
    } catch (java.lang.OutOfMemoryError e2) {
        // JVM had 99 units of "spare memory". 1 is used to create this OOM.
        try {
            e.printStackTrace();
        } catch (java.lang.OutOfMemoryError e3) {
            // JVM had 98 units of "spare memory". 1 is used to create this OOM.
            try {
                e.printStackTrace();
            } catch (java.lang.OutOfMemoryError e4) {
                // JVM had 97 units of "spare memory". 1 is used to create this OOM.
                try {
                    e.printStackTrace();
                } catch (java.lang.OutOfMemoryError e5) {
                    // JVM had 96 units of "spare memory". 1 is used to create this OOM.
                    try {
                        e.printStackTrace();
                    } catch (java.lang.OutOfMemoryError e6) {
                        // JVM had 95 units of "spare memory". 1 is used to create this OOM.
                        e.printStackTrace();
                        //........the JVM can't have infinite reserved memory, he's going to run out in the end
                    }
                }
            }
        }
    }
}

或者更简洁:

private void OnOOM(java.lang.OutOfMemoryError e) {
    try {
        e.printStackTrace();
    } catch (java.lang.OutOfMemoryError e2) {
        OnOOM(e2);
    }
}

最佳答案

JVM 从来没有真正耗尽内存。它预先对堆堆栈进行内存计算。

Structure of the JVM, Chapter 3 ,第 3.5.2 节指出:

  • If Java virtual machine stacks can be dynamically expanded, and expansion is attempted but insufficient memory can be made available to effect the expansion, or if insufficient memory can be made available to create the initial Java virtual machine stack for a new thread, the Java virtual machine throws an OutOfMemoryError.

对于,第 3.5.3 节。

  • If a computation requires more heap than can be made available by the automatic storage management system, the Java virtual machine throws an OutOfMemoryError.

因此,它在分配对象之前会提前进行计算。


发生的情况是 JVM 尝试为内存中称为永久代区域(或 PermSpace)的对象分配内存。如果分配失败(即使在 JVM 调用垃圾收集器尝试分配可用空间之后),它也会抛出 OutOfMemoryError。即使是异常也需要内存空间,所以会无限期抛出错误。

Further reading. ?此外,OutOfMemoryError 可能出现在不同的JVM structure. 中。

关于java - 当内存不足引发 OutOfMemoryError 时会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9261705/

相关文章:

language-agnostic - 讨论框架时 "light weight"是什么意思

math - float 学坏了吗?

language-agnostic - 为什么允许未定义的行为(而不是不编译/崩溃)?

java - 测试 Spring WebListener

java - Runnable 正在悄然死亡,最终执行外部,并且没有给出其他线索。我如何查看导致线程死亡的原因

windows - 从 DllMain 调用 LoadLibrary

language-agnostic - 将成就添加到企业级软件的技术

java - 传递给 Java main() 的命令行参数中的引号

java - 多态性赋值语句

java - 从 Java 类中提取字符串