OutOfMemoryErrorのcatch句内でなぜ処理できる?
JavaSE8です。
ヒープを使い切ってOutOfMemoryErrorがでたのであれば新しいオブジェクトをインスタンス化できないのでは?と思ったのですがキャッチ句内でもインスタンス生成できることが疑問です。
アドバイスのほど宜しくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答3件
0
OutOfMemoryErrorは、空いているメモリに対して、作成しようとするオブジェクトが大きい場合に発生します。空きがぴいたり0になったときではありません。newに失敗したときにそのオブジェクト分のメモリは確保されませんので、メモリはわずかながら空いている状態です。つまり、newに失敗したオブジェクトよりcatch句で生成するオブジェクトの方がサイズが小さければ作成できる場合があります。もし、空きがぎりぎりでオブジェクトを生成したり、同じぐらい大きなサイズのオブジェクトをcatch句で作成しようとすれば、再度OutOfMemoryErrorが発生します。
Java
1import java.util.List; 2import java.util.ArrayList; 3 4class OutMemoryTest { 5 public static void main(String[] args) { 6 System.out.println("[total] = [used] + [free] | [max]"); 7 List<int[][]> list = new ArrayList<>(); 8 try { 9 for (int i = 0; i < 1000; i++) { 10 list.add(new int[1000][1000]); 11 printMemory(); 12 } 13 } catch (OutOfMemoryError e) { 14 System.out.println("out of memory"); 15 printMemory(); 16 list.add(new int[1000][1000]); // 再度OutOfMemoryErrorが発生 17 } 18 printMemory(); 19 } 20 21 public static void printMemory() { 22 long total = Runtime.getRuntime().totalMemory(); 23 long free = Runtime.getRuntime().freeMemory(); 24 long max = Runtime.getRuntime().maxMemory(); 25 long use = total - free; 26 System.out.printf("%10d = %10d + %10d | %10d\n", 27 total, use, free, max); 28 } 29}
※ Runtime.getRuntime().〜Memory()
はヒープのメモリではなくJava VMのメモリであり、参考程度です。正確なヒープメモリの本当の空き具合はGCの動作をみるためにjstatなどを使う必要があります。
投稿2017/03/05 01:02
総合スコア21751
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
GCをやって不要なメモリーを回収しきった際の残りのメモリーがRESTであったときRESTより大きなサイズを確保しようとして発生するのがOutOfMemoryErrorですが、当然ながら確保失敗なのでまだメモリーの残量がRESTのままの状態でエラー処理が始まります。
ゆえにcatch節でREST未満のメモリーはまだ確保できるわけです。
しかしながら巨大なメモリーを確保しようとしてこのエラーが発生するのではなく、少しずつメモリーを圧迫していきながら最後に(RESTが非常に小さな値のときに)止めのnewをしようとした場合、catch節で利用可能なメモリー残量が非常に小さいため小さなオブジェクトをnewしようとしても、それさえできないということが起こるかもしれません。そうした場合は正しい例外処理ができるとは期待できないでしょう。
しかしアプリケーションを設計するときそのような状況にはならないように「メモリー見積もりをしておく」ことが普通でしょうから、メモリーリークバグがない限りメモリー不足のリカバリーができないという状況には普通ならないと思います。
投稿2017/03/05 00:57
編集2017/03/05 14:20総合スコア18404
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。