mirror of
https://github.com/jlengrand/quarkus-workshop.git
synced 2026-03-10 08:41:21 +00:00
122 lines
5.0 KiB
Plaintext
122 lines
5.0 KiB
Plaintext
= 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 package -Pnative` behind the scenes. The `-Pnative` argument selects the `native` maven profile which invokes the Graal compiler.
|
||
|
||
**This will take about 2-3 minutes to finish. Wait for it!**
|
||
|
||
[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 can use `-Dquarkus.native.container-runtime=[podman | docker]`. You'll need either Docker or https://podman.io[Podman,target=_blank] installed depending on which runtime you want to use!
|
||
====
|
||
|
||
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 -Dquarkus.http.port=8081
|
||
----
|
||
|
||
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://[::]:8081
|
||
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]
|
||
----
|
||
PID RSS COMMAND
|
||
16017 53816 target/people-1.0-SNAPSHOT-runner
|
||
----
|
||
|
||
This shows that our process is taking around 50 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:8081/hello/greeting/quarkus
|
||
----
|
||
|
||
You should see:
|
||
|
||
[source,none]
|
||
----
|
||
hello quarkus from <your-hostname>
|
||
----
|
||
|
||
Nice!
|
||
|
||
== Cleanup
|
||
|
||
Go to the Terminal in which you ran the native app and press kbd:[CTRL+C] to stop our native app (or close the Terminal window with the `X` button next to its title). **Be sure to leave your Live Coding Terminal open!**
|
||
|
||
== 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. |