JVM在内存不足错误期间的行为? List s = new ArrayList <string>(); </string>

时间:2011-10-13 11:31:00

标签: java

try {
    for(;;) {
        s.add("Pradeep");
    }
} finally {
    System.out.println("In Finally");
}

在try块中,jvm内存不足,那么当jvm没有内存时,joutm最终是如何阻塞的呢?

输出:

In Finally
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

6 个答案:

答案 0 :(得分:2)

大概System.out.println来电需要的内存少于s.add("Pradeep")来电。

例如,如果sArrayList,则s.add调用可能会导致列表尝试将其容量加倍。这可能是一个非常需要内存的操作,因此即使JVM无法执行这样相对昂贵的任务,JVM也能继续执行并不奇怪。

答案 1 :(得分:1)

这是更简单的代码,更好地展示了发生的事情:

    try {
        int[] a = new int[Integer.MAX_VALUE];
    } catch( Exception e ) {
        e.printStackTrace();
    }

数组的分配失败,但这并不意味着Java不再有空闲内存。如果将项添加到列表中,则列表会以跳转的形式增长。同时,该列表将需要VM的一半以上的内存(默认情况下约为64MB)。下一个添加将尝试分配一个太大的数组。

但这意味着VM仍有大约30MB未使用的堆用于其他任务。

如果您想让VM遇到麻烦,请使用LinkedList,因为它会线性增长。当最后一次分配失败时,只有很少的内存来处理异常:

    LinkedList<Integer> list = new LinkedList<Integer>();
    try {
        for(;;) {
            list.add(0); 
        }
    } catch( Exception e ) {
        e.printStackTrace();
    }

该程序需要更长时间才能终止,但仍会因错误而终止。也许Java会将部分堆放在一边以进行错误处理或错误处理,因此不需要分配内存(在执行代码之前就会进行分配)。

答案 2 :(得分:1)

  

在try块中,jvm内存不足,那么当jvm没有内存时,joutm最终是如何阻塞的呢?

JVM“耗尽内存”并在尝试分配对象或阵列失败时抛出OOME,因为该对象没有足够的可用空间 。这并不意味着一切都必须立即停止:

  • JVM可以愉快地继续做不需要创建任何新对象的事情。我很确定在这种情况下会发生这种情况。 (字符串文字已经存在,println方法的实现很可能将字符复制到先前分配的Buffer中。)

  • JVM可能会分配小于触发OOME的对象。

  • OOME的传播可能导致包含对象引用的变量超出范围,并且它们引用的对象可能变得无法访问。随后的new可能会触发回收所述对象的GC,为新对象腾出空间。


注意:JLS没有指定在加载类时必须创建表示该文字的String对象。但是,它肯定会说它可能在类加载时创建......这就是在任何体面的JVM中发生的事情。


另一个答案说:

  

也许Java会将部分堆放在一边以进行错误处理或错误处理不需要分配内存(分配在代码执行之前发生)。

我认为这是对的。但是,我认为这个特殊的堆区域仅在实例化OOME异常时使用,并填充堆栈跟踪信息。一旦发生这种情况,JVM就会回到使用常规堆。 (很容易得到一些证据。只需重试add块中的finally调用。如果成功,则证明某些东西可以提供更多可用于一般用途。)< / p>

答案 3 :(得分:0)

最后几乎总是执行。 抛出异常时,JVM尽可能多地收集内存,读取代码可能意味着它收集了整个s集合。

当到达finally时,它只需要在字符串池中创建一个新的字符串“In finally”不需要额外的内存,并且它没有问题,因为它之前释放了空间

尝试在最后打印s.size(),您将看到它无法执行此操作。 (编辑:如果在catch中,最后或在try块之后,有一行代码使用s集合,垃圾收集器在抛出OOME时无法收集它。这就是堆的原因内存几乎已满,因此任何新的对象分配都可能再次抛出另一个OOME。如果没有看到完整的代码,很难预测。)

答案 4 :(得分:0)

JVM实际上没有内存,无法继续。此错误表示无法分配内存,因此没有。这可能意味着它非常低。但是这里失败的是调整集合内部数组的大小。有很多内存可以让大型数据翻倍。所以它最终可以继续进行。

答案 5 :(得分:0)

当堆空间超过-Xmx标志设置的空间时,抛出错误,并且无法正常继续。错误传播,但它不会立即导致JVM关闭(在这种情况下退出系统,OOM错误中没有任何意义,因为它永远不会被抛出)。

由于JVM尚未退出,因此根据语言规范,它会尝试执行finally块。