This documentation may be out of date. See the latest version.

Native Image Build Configuration

Native Image supports a wide range of options to configure the native-image builder.

Table of Contents #

Embed a Configuration File #

We recommend that you provide the configuration for the native-image builder by embedding a file into a project JAR file. The native-image builder will also automatically pick up all configuration options provided in the META-INF/native-image/ directory (or any of its subdirectories) and use it to construct native-image command-line options.

To avoid a situation when constituent parts of a project are built with overlapping configurations, we recommended you use subdirectories within META-INF/native-image: a JAR file built from multiple maven projects cannot suffer from overlapping native-image configurations. For example:

  • foo.jar has its configurations in META-INF/native-image/foo_groupID/foo_artifactID
  • bar.jar has its configurations in META-INF/native-image/bar_groupID/bar_artifactID

The JAR file that contains foo and bar will then contain both configurations without conflict. Therefore the recommended layout to store configuration data in JAR files is as follows:

└── native-image
    └── groupID
        └── artifactID

Note that the use of ${.} in a file expands to the resource location that contains that exact configuration file. This can be useful if the file refers to resources within its subdirectory, for example, -H:ResourceConfigurationResources=${.}/custom_resources.json. Always make sure you use the option variants that take resources, that is, use -H:ResourceConfigurationResources instead of -H:ResourceConfigurationFiles. Other options that work in this context are:

  • -H:DynamicProxyConfigurationResources
  • -H:JNIConfigurationResources
  • -H:ReflectionConfigurationResources
  • -H:ResourceConfigurationResources
  • -H:SerializationConfigurationResources

By having such a composable file, building a native executable does not require any additional option on the command line. It is sufficient to run the following command:

$JAVA_HOME/bin/native-image -jar target/<name>.jar

To identify which configuration is applied when building a native executable, use native-image --verbose. This shows from where native-image picks up the configurations to construct the final composite configuration command-line options for the native image builder.

native-image --verbose -jar build/basic-app-0.1-all.jar
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/common/
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/buffer/
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/transport/
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/handler/
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/codec-http/
Executing [
    <composite configuration command line options for the image builder>

Typical examples of configurations that use a configuration from META-INF/native-image can be found in Native Image configuration examples.

Configuration File Format #

A file is a Java properties file that specifies configurations for native-image. The following properties are supported.


Use this property if your project requires custom native-image command-line options to build correctly. For example, the native-image-configure-examples/configure-at-runtime-example contains Args = --initialize-at-build-time=com.fasterxml.jackson.annotation.JsonProperty$Access in its file to ensure the class com.fasterxml.jackson.annotation.JsonProperty$Access is initialized at executable build time.


Sometimes it can be necessary to provide custom options to the JVM that runs the native-image builder. Use the JavaArgs property in this case.


This property specifies a user-defined name for the executable. If ImageName is not used, a name is automatically chosen: * native-image -jar <name.jar> has a default executable name <name> * native-image -cp ... fully.qualified.MainClass has a default executable name fully.qualified.mainclass

Note that using ImageName does not prevent you from overriding the name via the command line. For example, if contains ImageName=foo_app: * native-image -jar generates the executable foo_app but * native-image -jar application generates the executable application

Changing the Default Configuration Directory #

Native Image by default stores configuration information in the user’s home directory: $HOME/.native-image/. To change this default, set the environment variable NATIVE_IMAGE_USER_HOME to a different location. For example:

export NATIVE_IMAGE_USER_HOME= $HOME/.local/share/native-image

Order of Arguments Evaluation #

The options passed to native-image are evaluated from left to right. This also extends to options that are passed indirectly via configuration files in the META-INF/native-image directory. Consider the example where there is a JAR file that includes containing Args = -H:Optimize=0. You can override the setting that is contained in the JAR file by using the -H:Optimize=2 option after -cp <jar-file>.

Specifying Default Options for Native Image #

If you need to pass the same options every time you build a native executable, for example, to always generate an executable in verbose mode (--verbose), you can make use of the NATIVE_IMAGE_CONFIG_FILE environment variable. If the variable is set to the location of a Java properties file, the native-image tool will use the default setting defined in there on each invocation.

Write a configuration file and export NATIVE_IMAGE_CONFIG_FILE=$HOME/.native-image/ in ~/.bash_profile. Every time native-image is run it will implicitly use the arguments specified as NativeImageArgs, plus the arguments specified on the command line. Here is an example of a configuration file, saved as ~/.native-image/

NativeImageArgs = --configurations-path /home/user/custom-image-configs \

Memory Configuration for Native Image Build #

The native-image builder runs on a JVM and uses the memory management of the underlying platform. The usual Java command-line options for garbage collection apply to the native-image builder.

During the creation of a native executable, the representation of the whole application is created to determine which classes and methods will be used at runtime. It is a computationally intensive process that uses the following default values for memory usage:

-Xss10M \
-Xms1G \

These defaults can be changed by passing -J + <jvm option for memory> to the native-image tool.

The -Xmx value is computed by using 80% of the physical memory size, but no more than 14G per host. You can provide a larger value for -Xmx on the command line, for example, -J-Xmx26G.

By default, the native-image tool uses up to 32 threads (but not more than the number of processors available). For custom values, use the option -H:NumberOfThreads=....

For other related options available to the native-image tool, see the output from the command native-image --expert-options-all.

Specify Types Required to Be Defined at Build Time #

A well-structured library or application should handle linking of Java types (ensuring all reachable Java types are fully defined at build time) when building a native binary by itself. The default behavior is to throw linking errors, if they occur, at runtime. However, you can prevent unwanted linking errors by specifying which classes are required to be fully linked at build time. For that, use the --link-at-build-time option. If the option is used in the right context (see below), you can specify required classes to link at build time without explicitly listing classes and packages. It is designed in a way that libraries can only configure their own classes, to avoid any side effects on other libraries. You can pass the option to the native-image tool on the command line, embed it in a file on the module-path or the classpath.

Depending on how and where the option is used it behaves differently:

  • If you use --link-at-build-time without arguments, all classes in the scope are required to be fully defined. If used without arguments on command line, all classes will be treated as “link-at-build-time” classes. If used without arguments embedded in a file on the module-path, all classes of the module will be treated as “link-at-build-time” classes. If you use --link-at-build-time embedded in a file on the classpath, the following error will be thrown:
      Error: Using '--link-at-build-time' without args only allowed on module-path. 'META-INF/native-image/org.mylibrary/' in 'file:///home/test/myapp/MyLibrary.jar' not part of module-path.
  • If you use the --link-at-build-time option with arguments, for example,,demo.myLibrary.Name,..., the arguments should be fully qualified class names or package names. When used on the module-path or classpath (embedded in files), only classes and packages defined in the same JAR file can be specified. Packages for libraries used on the classpath need to be listed explicitly. To make this process easy, use the @<prop-values-file> syntax to generate a package list (or a class list) in a separate file automatically.

Another handy option is --link-at-build-time-paths which allows to specify which classes are required to be fully defined at build time by other means. This variant requires arguments that are of the same type as the arguments passed via -p (--module-path) or -cp (--class-path):

--link-at-build-time-paths <class search path of directories and zip/jar files>

The given entries are searched and all classes inside are registered as --link-at-build-time classes. This option is only allowed to be used on command line.

Connect with us