预测Java中的OutOfMemoryError

时间:2018-11-28 13:52:26

标签: java memory-management out-of-memory

考虑以下Java类:

public class Mem {
    public static void main(final String[] args) {
        printMem();
        final byte[] bytes = new byte[Integer.parseInt(args[0])];
        printMem();
    }

    private static void printMem() {
        System.gc();
        final Runtime runtime = Runtime.getRuntime();
        final long free = runtime.freeMemory();
        final long total = runtime.totalMemory();
        final long used = total - free;
        final long max = runtime.maxMemory();
        System.out.println(String.format(
                "Free: %,d; Used: %,d; Total: %,d; Max: %,d",
                free, used, total, max));
    }
}

这是字节数组的两种不同大小的输出:

$ java -Xmx1g Mem 700000000
Free: 250,063,176; Used: 1,595,064; Total: 251,658,240; Max: 954,728,448
Free: 92,445,200; Used: 700,278,256; Total: 792,723,456; Max: 954,728,448

$ java -Xmx1g Mem 800000000
Free: 250,063,176; Used: 1,595,064; Total: 251,658,240; Max: 954,728,448
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

最大可用内存约为950 MB。我可以分配700 MB的阵列,但不能分配800 MB的阵列。 我想堆空间相当于这950 MB的绝大部分,但是我不能分配800 MB的数组,因为堆上的可用空间不必是连续的。

在最大内存为7.5 GB的更复杂的应用程序中,尽管仅使用了2 GB,但分配500 MB阵列时却出现OutOfMemoryError。

有没有一种方法可以预测特定的内存分配在发生之前会导致OutOfMemoryError?

更新 该问题已被标记为与Check if there is enough memory before allocating byte array重复。但是,这两个问题存在显着差异。

  • 将分配包装到try-catch块中不是我的选择。我不控制分配。我可以为现有的Java应用程序编写类似插件的内容。
  • 我无法避免分配大对象。
  • 所提到的问题建议致电Runtime.getRuntime().freeMemory(),但我的问题中的样本表明,这种致电的结果极为不可靠。首先,如果使用total < max,则应用程序可以获得更多的内存。其次,即使空闲内存似乎比我分配的要多得多,分配也会失败。

0 个答案:

没有答案