Build Native Images for a Java Application
Use GraalVM and GluonFX to build native images for Java Applications
Having a hard time distributing Java Applications to your users? Are you using any paid tools for the same? What if I say, there is an Open-Source tool that will help you solve all the challenges you have faced?
Introducing you to GraalVM - A tool that helps to build native images for a Java Application.
GraalVM can be used to build native images that will have almost zero dependency requirements, have faster startup time and comparatively less memory usage.
Let's see how we can build native images for a simple Hello World program. I shall use IntelliJ Idea as my IDE and Maven as the build automation tool. You need to download GraalVM JDK from their official downloads page.
I quickly created a simple Hello World program in IntelliJ Idea as you can see below ๐
The pom.xml file generated by IntelliJ Idea is a very simple pom file and looks like this ๐
I will add the GraalVM maven build plugin configuration to the pom and finally, it is ๐
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>HelloWorld</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>20</maven.compiler.source>
<maven.compiler.target>20</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>0.9.27</version>
<extensions>true</extensions>
<configuration>
<imageName>HelloWorld</imageName>
<mainClass>HelloWorld</mainClass>
<outputDirectory>target/</outputDirectory>
<buildArgs>
<buildArg>--no-fallback</buildArg>
<buildArg>-H:+ReportExceptionStackTraces</buildArg>
<buildArg>--verbose</buildArg>
</buildArgs>
</configuration>
<executions>
<execution>
<id>build</id>
<goals>
<goal>build</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
GraalVM maven plugin requires three environment variables to be defined in the terminal session before generating native images. You can set those three environment variables by running these three commands ๐
export JAVA_HOME=~/Downloads/graalvm
export GRAALVM_HOME=~/Downloads/graalvm
export PATH=~/Downloads/graalvm/bin:$PATH
I have previously downloaded GraalVM JDK in my Downloads folder. You will replace Downloads
with the name of the folder in which graalvm is downloaded. You should rename the graalvm directory to only graalvm
i.e. you should remove any version text from the directory name, for simplicity.
At last comes the time to build the native executable for our Hello World program. You should run this ๐ command to build the native executable.
mvn clean package
This command does two things :
Deletes the previously created
target
directory (if it exists)Runs the
package
goal of the Maven lifecycle which includes thepackage
goal of GraalVM build plugin
The output of the above command is ๐
It builds the executable with the name HelloWorld
in the target
directory.
When we run the HelloWorld native image directly from the terminal, it runs without any Java Runtime ๐!
As you can see, the native application starts up in milliseconds which is very fast. This is how a simple Java app can be distributed as a native image. You can also build these images for MacOS, Windows and Linux on the respective systems by leveraging CI/CD pipelines' capabilities. I recommend GitHub Actions to build these native images and store them as artifacts for each run. You can check this GitHub Actions workflow file that I have created for a complex Java project - Drifty which is an Open-Source Interactive File Downloader System.
Drifty uses Java and JavaFX for its CLI and GUI counterparts. So, I had to use GluonFX Maven Plugin to build native images for the JavaFX application.
So, that is how you can build native images for any Java project. GraalVM also supports building the same for Micronaut, Helidon, Quarkus and Spring Boot applications.