= Building Native Images
:experimental:

Let’s now produce a native executable for our application. It improves the startup time of the application, and produces a minimal disk and memory footprint. The executable would have everything to run the application including the "JVM" (shrunk to be just enough to run the application), and the application. This is accomplished using https://graalvm.org[GraalVM,window=_blank].

GraalVM is a universal virtual machine for compiling and running applications written in JavaScript, Python, Ruby, R, JVM-based languages like Java, Scala, Groovy, Kotlin, Clojure, and LLVM-based languages such as C and C++. It includes ahead-of-time compilation, aggressive dead code elimination, and optimal packaging as native binaries that moves a lot of startup logic to _build-time_, thereby reducing startup time and memory resource requirements significantly.

image::native-image-process.png[native, 600]

GraalVM is already installed for you. Inspect the value of the `GRAALVM_HOME` variable in the Terminal with:

[source,sh,role="copypaste"]
----
echo $GRAALVM_HOME
----

== Build the image

Within the `pom.xml` is the declaration for the Quarkus Maven plugin which contains a profile for `native-image`:

[source,xml]
----
  <profile>
    <id>native</id>
    <build>
      <plugins>
        <plugin>
          <groupId>io.quarkus</groupId>
          <artifactId>quarkus-maven-plugin</artifactId>
          <version>${quarkus.version}</version>
          <executions>
            <execution>
              <goals>
                <goal>native-image</goal>
              </goals>
              <configuration>
                <enableHttpUrlHandler>true</enableHttpUrlHandler>
              </configuration>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
  </profile>
----

We use a profile because, you will see very soon, 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.

Create a native executable by once again opening the command palette and choose **Build Native Quarkus App**. This will execute `mvn clean package -Pnative` behind the scenes. The `-Pnative` argument selects the `native` maven profile which invokes the Graal compiler.

**This will take about 3-4 minutes to finish. Wait for it!**

[NOTE]
====
You can safely ignore any warnings like `Warning: RecomputeFieldValue.FieldOffset automatic substitution failed.` These are harmless and will be removed in future releases of Quarkus.
====

[NOTE]
====
Since we are on Linux in this environment, and the OS that will eventually run our application is also Linux, we can use our local OS to build the native Quarkus app. If you need to build native Linux binaries when on other OS's like Windows or Mac OS X, you'll need to have Docker installed and then use `mvn clean package -Pnative -Dnative-image.docker-build=true -DskipTests=true`.
====

In addition to the regular files, the build will produce `target/people-1.0-SNAPSHOT-runner`. This is a native Linux binary. Not a shell script, or a JAR file, but a native binary.

== Run native image

Since our environment here is Linux, you can _just run it_. In the terminal, run:

[source,sh,role="copypaste"]
----
target/people-1.0-SNAPSHOT-runner
----

Notice the amazingly fast startup time:

[source,none,role="copypaste"]
----
2019-07-10 04:04:11,817 INFO  [io.quarkus] (main) Quarkus 0.18.0 started in 0.015s. Listening on: http://[::]:8080
2019-07-10 04:04:11,818 INFO  [io.quarkus] (main) Installed features: [agroal, cdi, jdbc-h2, narayana-jta, resteasy]
----

That's 15 milliseconds to start up.

And extremely low memory usage as reported by the Linux `ps` utility. While the app is running, open another Terminal (click the `+` button on the terminal tabs line) and run:

[source,sh,role="copypaste"]
----
ps -o pid,rss,command -p $(pgrep -f runner)
----
You should see something like:

[source,none,role="copypaste"]
----
  PID   RSS  COMMAND
 4831 14184 target/getting-started-1.0-SNAPSHOT-runner
```
----

This shows that our process is taking around 13.8 MB of memory (https://en.wikipedia.org/wiki/Resident_set_size[Resident Set Size,window=_blank], or RSS). Pretty compact!

[NOTE]
====
The RSS and memory usage of any app, including Quarkus, will vary depending your specific environment, and will rise as the application experiences load.
====

Make sure the app is still working as expected (we'll use `curl` this time to access it directly). In a new Terminal run:

[source,sh,role="copypaste"]
----
curl http://localhost:8080/hello/greeting/quarkus
----

You should see:

[source,none,role="copypaste"]
----
hello quarkus from master
----

Nice!

== Cleanup

Go to the first Terminal tab and press kbd:[CTRL+C] to stop our native app (or close the Terminal window).

== Congratulations!

You've now built a Java application as an executable JAR and a Linux native binary. We'll explore the benefits of native binaries later in when we start deploying to Kubernetes.