5

我需要一些专家的理解

该程序不去捕获块(因为堆已满,但我想了解原因)

public class OOME_NotCatch {

    static List l = new ArrayList();
    static Long i = new Long(1);

    public static void main(String[] args) {
        try {
            while (true) {
                l.add(i);
                i++;
            }
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
            System.out.println("Encountered OutOfMemoryError");
        }
    }
}
//Console : Exception in thread "main" 

但是下面的程序运行良好,即使在获得 OOME 之后:

public class Catch_OOME_Collection {

    static List l = new ArrayList();

    public static void main(String[] args) {
        try {
            while (true) {
                l.add(new byte[1000000]);
                System.out.println("size " + l.size());
            }
        } catch (OutOfMemoryError e) {
            System.out.println("Encountered OutOfMemoryError");
            e.printStackTrace();
            System.out.println("size of list is  " + l.size());
            Iterator i = l.iterator();
            while(i.hasNext()){
                System.out.println(i.next().toString());
                i.remove();
            }
            while (true) {
                System.out.println("keep printing");
            }
        }
    }
}

在看到相同错误 OOME 的不同结果后,我有点困惑。请指导

4

3 回答 3

8

我的理解是,在第一个程序中,尝试分配一个新的 Long 对象时会抛出 OOME,它只占用几个字节的内存。这意味着堆已完全填满,并且不再有内存可用于运行 catch 块。

在第二个程序中,尝试分配 100 万字节的新数组时抛出 OOME。它失败了,但这可能意味着堆仍有 999,990 字节可用,这足以让 catch 块执行。

于 2013-08-10T22:00:20.997 回答
5

两个程序都进入了 catch 块。发生的情况是,它们中的任何一个都可能在设法生成和打印消息之前再次耗尽内存,并且程序会OutOfMemoryError立即收到新消息。

当我尝试第一个程序时,我确实看到了 catch 块生成的输出,这表明一旦抛出错误,程序执行是多么不可预测。在堆栈跟踪中,我看到 OOME 在尝试为ArrayList. 如果在创建较小的对象时抛出了 OOME,Long情况可能会有所不同。

需要注意的重要一点是,您无法真正OutOfMemoryError以有意义的方式捕获错误:错误可能会在非常不方便的地方抛出,从而使内部数据结构处于不一致的状态。在这种情况下,没有明显的不良影响,但是如果您调查 的内部字段,ArrayList您会发现它的modCount字段已经增加,而列表实际上没有被修改。

于 2013-08-10T22:01:17.007 回答
0

Long当分配一个或更可能增加内部数组的大小时,第一个程序会耗尽内存。

第二个程序在分配 a 时几乎肯定会耗尽内存byte[1000000].这可能比第一个程序失败的原因要大得多,因此现有内存可能远没有第一个情况那样耗尽,所以块中的代码catch可以成功分配一些Strings等来完成它必须做的事情。

于 2013-08-11T00:52:55.030 回答