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