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 ブロックを実行するためのメモリがもうないことを意味します。

2 番目のプログラムでは、100 万バイトの新しい配列を割り当てようとすると、OOME がスローされます。失敗しますが、ヒープにはまだ 999,990 バイトが使用可能であり、catch ブロックを実行するには十分です。

于 2013-08-10T22:00:20.997 に答える
5

どちらのプログラムも catch ブロックに入ります。何が起こるかというと、どちらかがメッセージを生成して出力する前に再びメモリ不足になる可能性があり、プログラムはOutOfMemoryErrorすぐに新しいメッセージを受け取ります。

最初のプログラムを試してみると、catch ブロックが生成する出力が表示されます。これは、エラーがスローされると、プログラムの実行がいかに予測不可能であるかを示しています。スタック トレースで、 の新しいバッキング配列を作成しようとしているときに OOME がスローされたことがわかりますArrayList。これは、catch ブロックを実行するのに十分なメモリがまだあったことを意味します。Long小さいオブジェクトの作成中に OOME がスローされた場合、状況が異なる可能性があります。

OutOfMemoryError注意すべき重要なことは、意味のある方法で を実際にキャッチすることはできないということです。エラーは非常に不便な場所でスローされ、内部データ構造が一貫性のない状態のままになる可能性があります。この場合、目に見える悪影響はありませんが、 の内部フィールドを調べると、実際にはリストが変更されていないのにフィールドがインクリメントされているArrayListことがわかります。modCount

于 2013-08-10T22:01:17.007 に答える