We are running our Java application with OpenJDK 17.0.7 in a Docker container with these arguments (these are only relevant to my question):
-XX:InitialRAMPercentage=75.0 -XX:MaxRAMPercentage=75.0 -XX:MaxMetaspaceSize=1G -XX:+UseG1GC
Here is a picture from JDK Mission Control showing how the application starts:
You can see that Committed size was not the same all the time. It started at 3GiB and then it grew up to ~6GiB.
Then I changed VM Arguments to use Xms/Xmx instead of RAMPercentage:
-Xms6G -Xmx6G -XX:MaxMetaspaceSize=1G -XX:+UseG1GC
And now I see the picture I expected to see - Committed size is equals to 6GiB from the startup:
Is it an expected behavior of InitialRAMPercentage? Shouldn't it work the same way as Xms? Am I missing something?
A common misconception is that the initial heap size is the minimum heap size. They are actually different and can be configured separately: -XX:InitialHeapSize
vs. -XX:MinHeapSize
.
In JDK 17, -Xms
is a shortcut to set both InitialHeapSize
and MinHeapSize
to the same value. In contrast, -XX:InitialRAMPercentage
affects InitialHeapSize
only, and therefore heap may shrink below the initial size.
If you want to prevent heap from resizing at runtime, disable heap shrinking with -XX:MaxHeapFreeRatio=100
, or disable adaptive size policy altogether: -XX:-UseAdaptiveSizePolicy
.
Note: -XX:MinRAMPercentage
does not help. Its name is confusing: the argument configures MaxHeapSize
, not MinHeapSize
- see JDK-8278492