Quarkus
Quarkus provides built-in support for building native images.
A new Quarkus project can be created using Quarkus CLI or code.quarkus.io. The created project already contains necessary code to build native images.
If Maven is used, the Maven configuration provides a native
profile to build native images.
The command below runs a Maven build to generate a native image.
./mvnw package -Pnative
The native image will be created in the target
directory with a suffix -runner
.
Quarkus can also use GraalVM running in a container to build native images.
./mvnw package -Pnative -Dquarkus.native.container-build=true
Build Container Images
Quarkus also provides two Dockerfile
s in the src/main/docker
directory to build container images using the native image file.
Dockerfile | Base image |
---|---|
Dockerfile.native | registry.access.redhat.com/ubi8/ubi-minimal:8.4 |
Dockerfile.native-distroless | quay.io/quarkus/quarkus-distroless-image:1.0 |
Native Image
Quarkus uses native-image
to build native images. To understand how native images are built, we can run the command below to generate native sources in the target/native-sources
directory.
./mvnw package -Dquarkus.package.type=native-sources
The native-sources
directory contains JAR files of the application and a native-image.args
file. The native-image.args
file contains the command line options passed to native-image
.
native-image $(cat native-image.args)
Configurations
Quarkus provides some configurations related to native images. These configurations are mapped to corresponding native-image
options. Updating their values will update the native-image.args
file. For example, when the property quarkus.native.enable-vm-inspection
is set to true
, the option -H:+AllowVMInspection
is added to native-image.args
. If there is no matching Quarkus properties, quarkus.native.additional-build-args
can be used to add extra options.
The table below shows the mappings.
Quarkus property | Native image option |
---|---|
quarkus.native.enable-http-url-handler | --enable-http |
quarkus.native.enable-https-url-handler | --enable-https |
quarkus.native.inline-before-analysis | -H:±InlineBeforeAnalysis |
quarkus.native.headless | -J-Djava.awt.headless=true/false |
quarkus.native.user-language | -J-Duser.language= |
quarkus.native.user-country | -J-Duser.country= |
quarkus.native.file-encoding | -J-Dfile.encoding= |
quarkus.native.add-all-charsets | -H:±AddAllCharsets |
quarkus.native.auto-service-loader-registration | -H:±UseServiceLoaderFeature |
quarkus.native.enable-fallback-images | -H:FallbackThreshold= |
quarkus.native.dump-proxies | -Dsun.misc.ProxyGenerator.saveGeneratedFiles=true/false |
quarkus.native.enable-vm-inspection | -H:±AllowVMInspection |
quarkus.native.enable-reports | -H:±PrintAnalysisCallTree |
quarkus.native.full-stack-traces | -H:±StackTrace |
quarkus.native.report-exception-stack-traces | -H:±ReportExceptionStackTraces |
quarkus.native.report-errors-at-runtime | -H:±ReportUnsupportedElementsAtRuntime |
quarkus.native.debug.enabled | -g and -H:DebugInfoSourceSearchPath= |
quarkus.native.enable-dashboard-dump | -H:DashboardDump= and -H:±DashboardAll |
Resources
Resources present in the META-INF/resources
directory will be included by default. Resources in other directories need to be declared explicitly. The properties quarkus.native.resources.includes
and quarkus.native.resources.excludes
specify the glob patterns to match for included and excluded resources, respectively. Multiple patterns are separated by comma.
Resources are typically put in the src/main/resources
directory. When specify the glob pattern, the directory name src/main/resources
is ignored, because files in src/main/resources
will be put in the root path of the built JAR. For example, the glob pattern input.text
will match the file src/main/resources/input.txt
.
Another choice is using a resource configuration file (See Resources). This file is usually put in the src/main/resources
directory. If the file name is resources-config.json
, then the property quarkus.native.additional-build-args
can be used to pass an extra option to native-image
.
quarkus.native.additional-build-args=-H:ResourceConfigurationFiles=resources-config.json
Reflections
If a class needs to be reflectively accessed, the @RegisterForReflection
annotation can be used.
import io.quarkus.runtime.annotations.RegisterForReflection;
@RegisterForReflection
public class MyModel {
}
If the source of reflectively accessed class cannot be modified, the class can be specified using @RegisterForReflection
. In the code below, ExternalClass
is registered for reflection.
@RegisterForReflection(targets = ExternalClass.class)
public class ExternalModelConfiguration {
}
@RegisterForReflection
has serval attributes to configure the reflection behavior, which matches the configurations in Native Image reflection config JSON file.
Attribute | Type | Default value | Description |
---|---|---|---|
targets | Class<?>[] | {} | Classes for reflection |
classNames | String[] | {} | Class names for reflection |
methods | boolean | true | If methods should be registered |
fields | boolean | true | If fields should be registered |
ignoreNested | boolean | true | If nested classes/interfaces should be registered |
serialization | boolean | false | If serialization should be supported |
Another choice is using a reflection configuration file. This is done by adding a reflect-config.json
file in the src/main/resources
directory and updating the property quarkus.native.additional-build-args
.
quarkus.native.additional-build-args=-H:ReflectionConfigurationFiles=reflect-config.json
Class Initialization
Quarkus initializes all classes at image build time by default. If some classes need to be initialized at runtime, the --initialize-at-run-time
option can be used.
quarkus.native.additional-build-args=--initialize-at-run-time=com.example.MyAppClass
Dynamic Proxy
Dynamic proxies need to be configure using JSON files.
quarkus.native.additional-build-args=-H:DynamicProxyConfigurationFiles=proxy-config.json
Internals
Quarkus generates the byte code of a feature in the build time. The class of this feature is io.quarkus.runner.AutoFeature
. It's an automatic feature.
In the implementation of this feature, API from GraalVM SDK is used to provide runtime configurations.