Native compilation builds a standalone executable from a Java application. Unlike a runnable JAR, the resulting binary runs without a JVM and does not wait for one to start. This makes fast startup and simpler distribution attractive for services where startup time matters, such as serverless applications. section 1.2.2 section 2.9
In Quarkus, a native build is a packaging choice rather than a requirement for production. GraalVM compiles the application ahead of time; Quarkus also supports creating native executables with Mandrel. The executable is specific to the platform on which it is built, so its filename may differ—for example, it may end in .exe. section 2.5.1 section 2.9 section 2.4.4
Listing 2.11 Quarkus native compilation commands
# Utilizing Maven profile $ ./mvnw package -Pnative # Gradle needs to use the system property $ ./gradlew build -Dquarkus.package.type=native # Or quarkus CLI for a general approach $ quarkus build --native
Build the same application with the native Maven profile, the Gradle package-type property, or the Quarkus CLI’s native flag. section 2.4.4
Listing 2.12 Running Quarkus native executable binary
$ ./target/quarkus-in-action-1.0.0-SNAPSHOT-runner __ ____ __ _____ ___ __ ____ ______ --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ --\___\_\____/_/ |_/_/|_/_/|_|\____/___/ 2024-09-26 17:04:48,328 INFO [io.quarkus] (main) quarkus-in-action 1.0.0-SNAPSHOT native (powered by Quarkus 3.15.1) started in 0.010s. Listening on: http://0.0.0.0:8080 2024-09-26 17:04:48,328 INFO [io.quarkus] (main) Profile prod activated. 2024-09-26 17:04:48,328 INFO [io.quarkus] (main) Installed features: [cdi, rest, smallrye-context-propagation, vertx]
The generated runner can be launched directly. The sample startup log reports a native application starting in 0.010 seconds. section 2.4.4
The build is less immediate than running the executable: producing a native image takes substantial processing and memory. One small application build took about a minute, including tests, and used approximately 2.8 GB of memory. Treat those figures as an example, not a sizing guarantee. section 2.4.4
Native compilation also constrains library integration. GraalVM needs to know ahead of time which program elements an application accesses through reflection. Quarkus extensions can supply that information for the libraries they integrate, reducing manual configuration; edge cases can still occur. Prefer an available extension when adding functionality that must work in a native executable. section 2.7.2 section 1.2.3
Choose the deployment form against the workload rather than startup alone. A native executable starts quickly, while a long-running JVM application can gain throughput as its just-in-time compiler optimizes observed execution paths. Ahead-of-time compilation cannot use those runtime observations in the same way. Quarkus build-time processing benefits applications independently of the native-image choice. section 2.5.1 section 1.2.2
