◀Table of Contents
Native Image Build Configuration
- Embedding a Configuration File
- Configuration File Format
- Memory Configuration for Native Image Build
- Runtime vs Build-Time Initialization
- Assisted Configuration of Native Image Builds
- Building Native Image with Java Reflection Example
- Agent Advanced Usage
Native Image supports a wide range of options to configure a native image build process.
Embedding a Configuration File
A recommended way to provide configuration is to embed a native-image.properties file into a project JAR file.
The Native Image builder will automatically pick up all configuration options provided anywhere below the resource location META-INF/native-image/
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, it is recommended to use “subdirectories” within META-INF/native-image
.
That way 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 conflicting with one another.
Therefore the recommended layout for storing native image configuration data in JAR files is the following:
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 wants to refer to resources within its “subfolder”, for example, -H:SubstitutionResources=${.}/substitutions.json
.
Always make sure to use the option variants that take resources, i.e., use -H:ResourceConfigurationResources
instead of -H:ResourceConfigurationFiles
.
Other options that are known to 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 an image does not require any additional arguments specified on command line. It is sufficient to just run the following command:
$JAVA_HOME/bin/native-image -jar target/<name>.jar
To debug which configuration data gets applied for the image building, use native-image --verbose
.
This will show 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 META-INF/native-image
based native image configuration can be found in Native Image configuration examples.
Configuration File Format
A native-image.properties
file is a regular Java properties file that can be
used to specify 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
has 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
gets initialized at image build time.
JavaArgs
Sometimes it can be necessary to provide custom options to the JVM that runs the native image builder.
The JavaArgs
property can be used in this case.
ImageName
This property can be used to specify a user-defined name for the image.
If ImageName
is not used, a name gets automatically chosen:
native-image -jar <name.jar>
has a default image name<name>
native-image -cp ... fully.qualified.MainClass
has a default image namefully.qualified.mainclass
Note that using ImageName
does not prevent the user to override the name later via command line.
For example, if foo.bar
contains ImageName=foo_app
:
native-image -jar foo.bar
generates the imagefoo_app
butnative-image -jar foo.bar application
generates the imageapplication
Order of Arguments Evaluation
The arguments passed to native-image
are evaluated left-to-right.
This also extends to arguments that get passed indirectly via META-INF/native-image
based native image configuration.
Suppose you have a JAR file that contains native-image.properties with Args = -H:Optimize=0
.
Then by using the -H:Optimize=2
option after -cp <jar-file>
you can override the setting that comes from the JAR file.
Specifying Default Options for Native Image
If there is a need to pass some options for every image build unconditionally, for example, to always generate an image in verbose mode (--verbose
), you can make use of the NATIVE_IMAGE_CONFIG_FILE
environment variable.
If it is set to a Java properties file, the Native Image builder 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
gets used, 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 Configuration Directory
Native Image by default stores the configuration information in user’s home directory – $HOME/.native-image/
.
In order to change the output directory, 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 Native Image Build
The native image build runs on the Java HotSpot VM and uses the memory management of the underlying platform. The usual Java HotSpot command-line options for garbage collection apply to the native image builder.
During the native image build, the representation of a whole program is created to figure out which classes and methods will be used at run time. It is a computationally intensive process. The default values for memory usage at image build time are:
-Xss10M \
-Xms1G \
These defaults can be changed by passing -J + <jvm option for memory>
to the native image builder.
The -Xmx
value is computed by using 80% of the physical memory size, but no more than 14G per server.
Providing a larger value for -Xmx
on command line is possible, e.g., -J-Xmx26G
.
By default, image building uses of up to 32 threads (but not more than the number of processors available). For custom values -H:NumberOfThreads=...
can be used.
Check other related options to the native image builder from the native-image --expert-options-all
list.
Runtime vs Build-Time Initialization
Building your application into a native image allows you to decide which parts of your application should be run at image build time and which parts have to run at image run time.
All class-initialization code (static initializers and static field initialization) of the application you build an image for is executed at image run time by default.
Sometimes it is beneficial to allow class initialization code to get executed at image build time for faster startup (e.g., if some static fields get initialized to run-time independent data).
This can be 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 image run time.
For more information please have a look at Native Image configuration examples.
For more information, continue reading to the Class Initialization in Native Image guide.