Skip to main content

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 Dockerfiles in the src/main/docker directory to build container images using the native image file.

DockerfileBase image
Dockerfile.nativeregistry.access.redhat.com/ubi8/ubi-minimal:8.4
Dockerfile.native-distrolessquay.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 propertyNative 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.

Register for reflection
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.

Register external class
@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.

AttributeTypeDefault valueDescription
targetsClass<?>[]{}Classes for reflection
classNamesString[]{}Class names for reflection
methodsbooleantrueIf methods should be registered
fieldsbooleantrueIf fields should be registered
ignoreNestedbooleantrueIf nested classes/interfaces should be registered
serializationbooleanfalseIf 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.