Мой тестовый код:
int SIZE = 1900;
int[][] array = new int[SIZE][];
for (int i = 0; i < SIZE; i++) {
array[i] = new int[1024 * 1024 / 4]; // 1MB
Thread.sleep(10);
if (i % 100 == 0 && i != 0) {
System.out.println(i + "Mb added");
}
}
Запускаю с аргументами в java 8 -Xmx2048m -XX:+UseG1GC -XX:+PrintGCDetails
И это не удается с OutOfMemory, когда потребляется только 1G.
Heap
garbage-first heap total 2097152K, used 1048100K [0x0000000080000000, 0x0000000080104000, 0x0000000100000000)
region size 1024K, 1 young (1024K), 0 survivors (0K)
Metaspace used 3273K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 358K, capacity 388K, committed 512K, reserved 1048576K
Я вижу, что выделенный размер G1 составляет 2 ГБ, и я полагаю, что JVM пытается выделить больше и терпит неудачу с OOM. Но почему он пытается выделить больше, если половина памяти свободна?
С UseConcMarkSweepGC
он работает нормально, и массив был полностью заполнен.
total 2097152K, used 1048100K
. Я проверял это как на Windows, так и на Linux. Поведение такое же - person Eugene To   schedule 29.08.2017array[i] = new int[1024 * 1024 / 4];
. Вот это место определенно вызывает OOM. Но обычно OOM может быть выброшен из любого места, которое не имеет ничего общего с основной причиной этого OOM. - person Eugene To   schedule 29.08.2017