Skip to main content

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.

ValuesDescriptionNote
serialSerial GCDefault value
epsilonEpsilon GCOnly available with GraalVM 21.2 or later
G1G1 GCOnly available with Oracle GraalVM and GraalVM EE
Specify the GC
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:

OptionDescription
-Xmxthe maximum heap size in bytes
-Xmsthe minimum heap size in bytes
-Xmnthe size of the young generation in bytes
-R:MaximumHeapSizePercentthe 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:MaxHeapSizethe default maximum heap size in bytes at image build time
-R:MinHeapSizethe default minimum heap size in bytes at image build time
-R:MinHeapSizethe default minimum heap size in bytes at image build time
-XX:MaxDirectMemorySizethe maximum size of direct buffer allocations.
Configure Memory
./app -Xms64m -Xmx256m -Xmn16m
tip

The MaximumHeapSizePercent option can also be used at build time to specify the default value.

native-image -R:MaximumHeapSizePercent=25 Main
Default memory settings

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.
Enable GC Logs
./app -XX:+PrintGC -XX:+VerboseGC