考虑以下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重复。但是,这两个问题存在显着差异。
Runtime.getRuntime().freeMemory()
,但我的问题中的样本表明,这种致电的结果极为不可靠。首先,如果使用total < max
,则应用程序可以获得更多的内存。其次,即使空闲内存似乎比我分配的要多得多,分配也会失败。