如果JVM堆内存已满,并且您尝试创建一个新对象,将会发生什么

时间:2019-02-17 15:19:47

标签: java

如果JVM堆已满,并且所有对象都是强引用,那么现在,如果您将创建一个新对象,那么将会发生什么以及将在哪个内存中创建该对象。 (不会出现OOM错误)

2 个答案:

答案 0 :(得分:3)

如果没有足够的可用空间,则JVM将运行垃圾收集器(通常是“完整” GC)。如果运行GC后 still 可用空间不足,则试图new对象的线程将抛出OutOfMemoryError异常。

  • 如果OOME在主线程上并且未被捕获,则JVM将退出。
  • 如果OOME被捕获或未抛出在“主”线程上,则JVM将尝试继续。

将堆栈展开到捕获点 可能会使足够的对象无法访问,从而JVM能够继续(在另一个GC之后)。但是,当发生OOME时,恢复代码通常无法确定或消除可能已经发生的损坏。例如对象创建不正确,其他线程可能已因OOME而死亡。

从OOMEs恢复通常是有问题的,是否应该尝试还存在争议:

  • 您可能无法正确恢复。应用程序/服务器/任何东西可能最终都处于损坏状态。
  • 如果OOME的原因是内存泄漏,则很容易以增加的频率再次出现。最好让应用程序死掉并重新启动。
  • 如果OOME的原因是JVM的内存太小或任务太大,则恢复并重试通常将无法工作。

答案 1 :(得分:1)

根据JLS

  

如果对类实例创建表达式的求值发现没有足够的内存来执行创建操作,则抛出OutOfMemoryError。此检查在任何参数表达式求值之前进行。

它甚至还提供了一个示例程序,该程序最终将引发OOM ...

class List {
    int value;
    List next;
    static List head = new List(0);
    List(int n) { value = n; next = head; head = this; }
}
class Test {
    public static void main(String[] args) {
        int id = 0, oldid = 0;
        try {
            for (;;) {
                ++id;
                new List(oldid = id);
            }
        } catch (Error e) {
            List.head = null;
            System.out.println(e.getClass() + ", " + (oldid==id));
        }
    }
}

在我的系统上,花了几分钟,但最终到了:

$ javac Test.java 
$ java Test
class java.lang.OutOfMemoryError, false