Now, it's time to check what Quarkus can do to turn our bytecode into a native executable. This kind of magic is done under the hood by a Maven profile named native, which is included out of the box when you scaffold your application:
<profile>
<id>native</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemProperties>
<native.image.path>${project.build.directory}
/${project.build.finalName}-runner
</native.image.path>
</systemProperties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<quarkus.package.type>native</quarkus.package.type>
</properties>
</profile>
In addition, maven-failsafe-plugin has been automatically configured to run integration-test goal since we've set the path where the native image has been built as the system property.
Next, create a native executable by executing the following command:
$ mvn package -Pnative
The plugin will start analyzing the classes and packaging that's used in your application, along with the call tree. The resulting output will be a super lean executable that contains just a thin JVM layer (narrow enough to just execute the application) and the application itself.
You should see something similar to the following at the end of your output:
[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 60485ms
Along with the JAR file containing the compressed bytecode for your application, the following executable will be generated in the target folder:
Nov 11 14:49 hello-rest-1.0-SNAPSHOT-runner
As you can see, with approximately 20 MB, we have an executable application runtime that contains all the libraries and just what it needs from the JVM to run our application. You can execute it with the following command:
$ target/hello-rest-1.0-SNAPSHOT-runner
In as little as 0.006s, we got our service up and running. This can be seen in the console log:
2019-11-11 14:53:38,619 INFO [io.quarkus] (main) hello-rest 1.0-SNAPSHOT (running on Quarkus 1.0.0.CR1) started in 0.014s. Listening on: http://0.0.0.0:8080
2019-11-11 14:53:38,619 INFO [io.quarkus] (main) Profile prod activated.
2019-11-11 14:53:38,619 INFO [io.quarkus] (main) Installed features: [cdi, resteasy]
Let's check the memory usage of this compact application by executing the ps command:
$ ps -o pid,rss,command -p $(pgrep -f hello-rest)
Here is the output I have collected from my laptop:
PID RSS COMMAND
27919 18720 target/hello-rest-1.0-SNAPSHOT-runner
Although the output may vary depending on your environment, the Resident Set Size (RSS) shows that the process is taking about 18 MB of memory, which is a fraction of the minimum memory size required for a Java application.
Now, let's execute it to check the result:
$ curl http://localhost:8080/helloworld
hello
As you can see, the result didn't change when we turned our application into a native application.