Xms
specifies the initial memory allocation. Xmx sets the maximum memory allocation.
For a regional collector, like G1GC or Shenandoah, the pre-allocate the memory because they divide the heap in sections.
On the other hand, the ParallelGC, which is a generational collector – will divide the heap in generations: young, survivor, tenure generation.
But interestingly, ParallelGC will not pre-allocate the memory and as consequence one could cheat the memory and set a Xmx and Xms higher than the memory available in the box, on the example below it has only 2Gb available:
#grep MemTotal /proc/meminfo
MemTotal: 2000000 kB <-------- 2Gb
$JAVA_HOME/bin/java -Xmx20G -Xms2520m -Dfoo=example -XX:+PrintFlagsFinal GetValue <--- just prints string: Running Example
Running example
In contrast to G1/Shenandoah, which will pre-allocate/allocated at the start directly and it will crash right away:
$JAVA_HOME/bin/java -XX:+ShenandoahLogDebug -Xmx20G -Xms1700m -XX:+UseG1GC -Dfoo=example GetValue
OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x00000002c0000000, 1782579200, 0) failed; error='Cannot allocate memory' (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 1782579200 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /root/test_openjdk8_shenandoah_bug/test_application/hs_err_pid28074.log <------------------------------------------------------ crash log with insufficient memory
$JAVA_HOME/bin/java -XX:+ShenandoahLogDebug -Xmx20G -Xms1600m -XX:+UseG1GC -Dfoo=example GetValue
Running Application <------------------------------------------------------------------------------------------------------------ using Xms as 1.6Gb maximum
But of course, eventually setting a higher xms/xmx than the max memory available on the box it will crash, even if it is not pre-allocated/allocated in the start of the JVM.