Memory Management
Comparing to Java apps running in JVM mode, native Java apps have some limitations of memory management.
Garbage Collectors
Native Image only provides three garbage collectors:
- The Serial GC is the default GC in GraalVM.
- The Epsilon GC is a no-op garbage collector.
- The G1 GC is only available with Oracle GraalVM and GraalVM EE.
The garbage collector is specified with the --gc
option. The table below shows allowed values of this option.
Values | Description | Note |
---|---|---|
serial | Serial GC | Default value |
epsilon | Epsilon GC | Only available with GraalVM 21.2 or later |
G1 | G1 GC | Only available with Oracle GraalVM and GraalVM EE |
native-image --gc=serial Main
Serial GC
The Serial GC is optimized for low footprint and small Java heap sizes. It's a non-parallel, non-concurrent, stop and copy GC.
If GraalVM CE is the only choice, then Serial GC is the only choice for most native Java apps. Although Serial GC is not very performant, it may still be good enough.
Epsilon GC
The Epsilon GC does not do any garbage collection and therefore never frees any allocated memory. This GC is primarily used for very short running applications that only allocate a small amount of memory.
In cloud-native architecture, it's common to run scheduling tasks to perform periodical actions. This kind of tasks are typically scheduled using Kubernetes CronJob
. When running these tasks, it's reasonable to use Epsilon GC. However, the maximum heap size needs to be configured to be larger than the required memory.
G1 GC
G1 is a generational, incremental, parallel, mostly concurrent, stop-the-world, and evacuating GC.
G1 is the default GC since Java 11. If GraalVM EE is used, then G1 is a better choice.
Memory Configurations
Memory of native images can be configured with the following options:
Option | Description |
---|---|
-Xmx | the maximum heap size in bytes |
-Xms | the minimum heap size in bytes |
-Xmn | the size of the young generation in bytes |
-R:MaximumHeapSizePercent | the percentage of the physical memory size that is used as the maximum Java heap size. This option is used only when -Xmx is not present. Serial and epsilon GC only. |
-R:MaxHeapSize | the default maximum heap size in bytes at image build time |
-R:MinHeapSize | the default minimum heap size in bytes at image build time |
-R:MinHeapSize | the default minimum heap size in bytes at image build time |
-XX:MaxDirectMemorySize | the maximum size of direct buffer allocations. |
./app -Xms64m -Xmx256m -Xmn16m
The MaximumHeapSizePercent
option can also be used at build time to specify the default value.
native-image -R:MaximumHeapSizePercent=25 Main
By default, a native image uses young generation of size 256MB
with no survivor region. The maximum heap size is set to 80% of the physical memory. It's recommended to always configure memory explicitly.
GC Logs
GC log can be enabled using the -XX:+PrintGC
and -XX:+VerboseGC
options.
-XX:+PrintGC
prints basic information about every garbage collection.-XX:+VerboseGC
prints detailed information about every garbage collection.
./app -XX:+PrintGC -XX:+VerboseGC