-3

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

4

2 回答 2

4

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

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

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

从 OOME 中恢复通常是有问题的,您是否应该尝试以下方法值得商榷:

  • 您可能无法正常恢复。应用程序/服务器/任何东西都可能最终处于损坏状态。
  • 如果 OOME 的原因是内存泄漏,那么它很可能会随着频率的增加而再次发生。最好让应用程序死掉并重新启动。
  • 如果 OOME 的原因是 JVM 的内存太小或任务太大,那么恢复并重试通常是行不通的。
于 2019-02-17T15:27:22.693 回答
1

根据JLS

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

它甚至为您提供了一个示例程序,该程序将抛出 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 测试.java
$ java 测试
类 java.lang.OutOfMemoryError,假
于 2019-02-17T15:25:56.220 回答