G1GC OutOfMemory Too Early

My test code is:

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"); } } 

I run it with arguments in java 8 -Xmx2048m -XX:+UseG1GC -XX:+PrintGCDetails

And it does not work with OutOfMemory when only 1G is consumed.

 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 

I see that the size of the allocated G1 is 2G, and I suppose the JVM is trying to allocate more and does not work with OOM. But why is he trying to allocate more if half the memory is free?

With UseConcMarkSweepGC it works fine and the array is full.

+5
source share
2 answers

I am sure this is due to Humongous Allocations .
If you add this option

-XX: + PrintAdaptiveSizePolicy

You will see that most of the allocations are 1048592 bytes, which does not correspond to either 50% or even 100% of one G1 area (which, as you can see, is 1024K = 1048576 bytes). I assume this means that each array occupies at least two regions. Since this is an extensive distribution, most of the free space in the second region cannot be used. This quickly causes fragmentation of the heap, making further distribution impossible.

+6
source

Agree with @yegodm. The solution is to increase the heap area with -XX: G1HeapRegionSize to ensure that previous Humongous objects are no longer Humongous and will follow a regular distribution path. Read more about the distribution of posted objects here 1

+1
source

Source: https://habr.com/ru/post/1271332/


All Articles