質問: OutOfMemoryErrorのcatch句内でなぜ処理できる? JavaSE8です。 ヒープを使い切ってOutOfMemoryErrorがでたのであれば新しいオブジェクトをインスタンス化できないのでは?と思ったのですがキャッチ句内でもインスタンス生成できることが疑問です。 アドバイスのほど宜しくお願いいたします。
回答: OutOfMemoryErrorは、空いているメモリに対して、作成しようとするオブジェクトが大きい場合に発生します。空きがぴいたり0になったときではありません。newに失敗したときにそのオブジェクト分のメモリは確保されませんので、メモリはわずかながら空いている状態です。つまり、newに失敗したオブジェクトよりcatch句で生成するオブジェクトの方がサイズが小さければ作成できる場合があります。もし、空きがぎりぎりでオブジェクトを生成したり、同じぐらい大きなサイズのオブジェクトをcatch句で作成しようとすれば、再度OutOfMemoryErrorが発生します。 ``` import java.util.List; import java.util.ArrayList; class OutMemoryTest { public static void main(String[] args) { System.out.println("[total] = [used] + [free] | [max]"); List list = new ArrayList<>(); try { for (int i = 0; i < 1000; i++) { list.add(new int[1000][1000]); printMemory(); } } catch (OutOfMemoryError e) { System.out.println("out of memory"); printMemory(); list.add(new int[1000][1000]); // 再度OutOfMemoryErrorが発生 } printMemory(); } public static void printMemory() { long total = Runtime.getRuntime().totalMemory(); long free = Runtime.getRuntime().freeMemory(); long max = Runtime.getRuntime().maxMemory(); long use = total - free; System.out.printf("%10d = %10d + %10d | %10d\n", total, use, free, max); } } ``` ※ `Runtime.getRuntime().〜Memory()`はヒープのメモリではなくJava VMのメモリであり、参考程度です。正確なヒープメモリの本当の空き具合はGCの動作をみるためにjstatなどを使う必要があります。