Native Executable JAR

Introduction

Now let’s produce a native executable for our application. It improves the startup time of the application and produces a minimal disk footprint. The executable has everything needed to run the application including the JVM (shrunk to be just enough to run the application) and the application itself.  

We will be using GraalVM, which includes a native compiler for producing native images for a number of languages, including Java. Ensure the location of the GraalVM installation is set by checking the appopriate environment variable:

 

echo $GRAALVM_HOME
That value should point to the installation of GraalVM. You can also test that it's installed correctly by running the included java executable:

 

$GRAALVM_HOME/bin/java -version

The output should be similar to the following (the relevant part is that it indicates it's using the GraalVM):

openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment GraalVM CE 21.1.0 (build 11.0.11+8-jvmci-21.1-b05)
OpenJDK 64-Bit Server VM GraalVM CE 21.1.0 (build 11.0.11+8-jvmci-21.1-b05, mixed mode, sharing)

 

Building the Native Image

Within the pom.xml is the declaration for the Maven profile named "native":

 

<profile>
    <id>native</id>
    <activation>
    <property>
        <name>native</name>
    </property>
    </activation>
    <build>
    ...
    <properties>
    <quarkus.package.type>native</quarkus.package.type>
    </properties>
</profile>

 

We use a profile because packaging the native image takes a few seconds. However, this compilation time is only incurred once, as opposed to every time the application starts, which is the case with other approaches for building and executing JARs.

 

Before building the native image, you need to know which container runtime you're going to use, either Docker or Podman. The Maven command requires this value (in lowercase) under the parameter quarkus.native.container-runtime. This example uses Podman, so if you're using Docker be sure to update the command accordingly.

 

From within the project directory, create the native executable by running:

 

mvn clean package -Pnative -DskipTests -Dquarkus.native.container-runtime=podman

 

In addition to the other JARs normally produced by the package goal, the native profile creates a file named getting-started-1.0.0-SNAPSHOT-runner.

 

Running the Native Image

As a native image, you simply run the file to start the application:

 

target/getting-started-1.0.0-SNAPSHOT-runner
In another terminal, ensure the application started correctly by using the URL from the previous examples:

 

curl localhost:8080/hello

 

Cleaning Up

Stop the native application by pressing CTRL-C in its terminal.

 

Next Steps

You've now built a Java application as an executable JAR and a Linux native binary. Now let's give our application superpowers by deploying to Kubernetes as a Linux container image.