如果jvm堆已满,并且所有对象都是强引用,现在,如果您将创建一个新对象,那么将会发生什么以及在哪个内存中创建对象。(没想到OOM错误)
如果没有足够的可用空间,JVM将运行垃圾收集器(通常是"完整" GC)。如果运行GC后仍然没有足够的可用空间,则试图new
的线程将抛出OutOfMemoryError
异常。
- 如果OOME在主线程上并且未捕获,JVM将退出。
- 如果抓住了OOME或未将其扔到"主"线程上,JVM将尝试进行。
将堆栈放松到捕获点 May 使足够的对象无法到达以使JVM能够继续(在另一GC之后)。但是,当发生OOME时,恢复代码通常无法确定或撤消可能发生的损害;例如未正确创建的对象,可能死于OOME的其他线程。
从OOMES恢复通常是有问题的,是否应该尝试:
是有争议的:- 您可能无法正确恢复。应用程序/服务器/任何可能最终处于破损状态。
- 如果OOME的原因是内存泄漏,则可能以增加频率重复出现。申请可以死亡并重新启动。
- 如果OOME的原因是JVM的内存太小或任务太大,则恢复并尝试重新尝试。
按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测试java.lang.outofmemoryerror,false