openjdk 11.0.14.1 2022-02-08
Consider the following simple Java program.
public static void main( String[] args ){
int i[] = new int[Integer.MAX_VALUE / 2];
}
Here int
is 4 byte in size so allocating int[Integer.MAX_VALUE / 2]
requires 4G
of free heap size. Now let's run the program with different options.
I. -XX:+UseParallelGC -Xmx5g
Result: Crash with OutOfMemoryError
.
Even in spite of the fact that heap size is large enough. It's clear since the -XX:NewSize
is 1310 MB
by default and the Old generation is not large enough.
II. -XX:+UseParallelGC -Xmx5g -XX:MaxNewSize=128m -XX:NewSize=128m
Result: Completed normally
The application runs fine since the Old generation is large enough to hold the array allocation.
Now let's change the collector from Parallel
to G1
III. -XX:+UseG1GC -Xmx5g -XX:MaxNewSize=128m -XX:NewSize=128m
Result: Crash with OutOfMemoryError
.
And this is what I have no idea about. I thought that adjusting -XX:G1HeapWastePercent
would help, but it didn't.
Why can't G1
hold the allocation of the array and what options to adjust in order to fix it?
This is a JVM bug JDK-8279241 "G1 Full GC does not always slide memory to bottom addresses". It should be resolved in JDK 19.
The workaround is to disable Class Data Sharing. The test does not fail with -Xshare:off