◀Table of Contents
Native Image Build Configuration
- Embedding a Configuration File
- Configuration File Format
- Memory Configuration for Building a Native Executable
- Runtime vs Build Time Initialization
- Specifying Types Required to Be Defined at Build Time
Native Image supports a wide range of options to configure the native-image
tool.
Embedding a Configuration File
We recommend that you provide the configuration for the native-image
tool by embedding a native-image.properties file into a project JAR file.
The native-image
tool 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 arguments.
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:
META-INF/
└── native-image
└── groupID
└── artifactID
└── native-image.properties
Note that the use of ${.}
in a native-image.properties file expands to the resource location that contains that exact configuration file.
This can be useful if the native-image.properties file refers to resources within its subdirectory, for example, -H:SubstitutionResources=${.}/substitutions.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:SubstitutionResources
-H:SerializationConfigurationResources
By having such a composable native-image.properties file, building a native executable does not require any additional arguments 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/native-image.properties
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/buffer/native-image.properties
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/transport/native-image.properties
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/handler/native-image.properties
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/codec-http/native-image.properties
...
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 native-image.properties file is a Java properties file that specifies native image configurations. The following properties are supported.
Args
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 native-image.properties file to ensure the class com.fasterxml.jackson.annotation.JsonProperty$Access
is initialized at executable build time.
JavaArgs
Sometimes it can be necessary to provide custom options to the Java VM that runs the native-image
tool.
Use the JavaArgs
property in this case.
ImageName
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 the user overriding the name via the command line.
For example, if foo.bar
contains ImageName=foo_app
:
* native-image -jar foo.bar
generates the executable foo_app
but
* native-image -jar foo.bar application
generates the executable application
Order of Arguments Evaluation
The arguments passed to native-image
are evaluated from left to right.
This also extends to arguments 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 native-image.properties 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/default.properties
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/default.properties:
NativeImageArgs = --configurations-path /home/user/custom-image-configs \
-O1
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
Memory Configuration for Building a Native Executable
The native-image
tool runs on a Java VM and uses the memory management of the underlying platform.
The usual Java command-line options for garbage collection apply to the native-image
tool.
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
.
Runtime vs Build-Time Initialization
When you build a native executable, you can decide which elements of your application are run at build time, and which elements are run at executable run time.
By default, all class-initialization code (static initializers and static field initialization) of the application is run at executable run time.
Sometimes it is beneficial to run class initialization code when the executable is built. For example, for faster startup if some static fields are initialized to values that are runtime-independent.
This is controlled with the following native-image
options:
--initialize-at-build-time=<comma-separated list of packages and classes>
--initialize-at-run-time=<comma-separated list of packages and classes>
In addition to that, arbitrary computations are allowed at build time that can be put into ImageSingletons
that are accessible at run time. For more information, see Native Image configuration examples.
Specifying 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 executable by itself.
The default behavior is to throw linking errors, if they occur, at run time.
However, you can prevent unwanted linking errors by specifing 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 native-image.properties
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 anative-image.properties
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 anative-image.properties
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/native-image.properties' 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,--link-at-build-time=foo.bar.Foobar,demo.myLibrary.Name,...
, the arguments should be fully qualified class names or package names. When used on the module-path or classpath (embedded innative-image.properties
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.