In our recent guide to JavaFX, we summarized the key features of this platform and compared it to the most prominent competitors. If you are still wondering whether JavaFX is worth learning, refer to the guide. For those of you who have already mastered the software, we suggest going a step further and integrate it with native image technology. So let’s get our hands dirty and turn a JavaFX application into a native executable using Liberica Native Image Kit!
- What is Liberica Native Image Kit?
- Turn a JavaFX app into a native image!
- Further reading
What is Liberica Native Image Kit?
Liberica Native Image Kit (NIK) is a utility based on the GraalVM Community Edition. It helps to convert JVM-based applications into native executables. Liberica NIK enhances the experience of writing desktop applications as the native image takes up less disc space and starts up almost instantly.
The benefits of using Liberica NIK in your enterprise development:
- Supports a wide variety of platforms, features, and languages. We support Windows, Linux, and MacOS, including ARM-based Macs. Starting with version 21.3, Liberica NIK works with AWT/Swing and OpenJFX
- Always on the latest versions of GraalVM CE and Liberica JDK with eliminated CVEs and bug fixes
- Receives support from the engineers who develop the product
Turn a JavaFX app into a native image!
Enable native compilation
First, you need to download and install Liberica NIK. Go to the Liberica NIK Download Center and choose NIK version 22 for Java 11 or 17. You need the Full version as it includes LibericaFX, an instance of OpenJFX.
Download the package and follow the instructions to install the utility on your platform. macOS users should get the .dmg package to avoid any issues with running Liberica NIK.
You are now ready to compile Java applications natively. You have several options:
- Manual invocation. From your NIK installation, run \
native-image <args class="bs-link" target="_blank"> -jar <your application jar>
- Configure Maven build as described here
- Configure Gradle build as described here
In all three cases, arguments you pass to the
native-image invocation should include:
--add-modules javafx.controls,javafx.fxml,javafx.swingto include JavaFX modules (may change with the next release)
- Your application is likely to use resources such as icons or images. These resources must be made known to
native-imageso that it includes them in the resulting executable. There are two options to include and exclude resource identifiers, and you can use wildcards there: \
-H:IncludeResources='com.fxapp.resources.images.*' \ -H:ExcludeResources='com.fxapp.resources.unused.*'
Alternatively, resources can be configured using JSON files. Many applications make use of dynamic language features such as reflective or JNI access. In this case, the feature being used, such as the name of the method called, is not known at image build time, so NIK cannot figure out exactly which method is called. These dynamic feature usages must be configured beforehand using JSON files as described here.
You can create JSON files using the native image agent. Run your application with the agent enabled, probably several times to exercise different code paths. The agent captures dynamic feature accesses and creates configuration files automatically. These files can be passed to
native-image without further editing.
Compile the application
Let us now compile a JavaFX app natively. We will use the BrickBreaker game as an example. You can utilize your own app or select a JavaFX demo on GitHub. BrickBreaker requires no dynamic feature configuration. At the same time, it uses lots of images that need to be included in the resulting executable. In this example, image names are passed using
-H:IncludeResources with a regular expression:
$ native-image --add-modules javafx.controls,javafx.fxml,javafx.swing -H:IncludeResources='ensemble.samples.shared-resources.brickImages.*' -jar BrickBreaker.jar
After the compilation has finished, run
$ ls -lh BrickBreaker
Speed and memory comparison
The figures below were obtained on an Intel Core i7 laptop running Ubuntu Linux.
|Liberica JRE 220.127.116.11||Native Image made with Liberica NIK 22.2.0-JDK17|
|Executable size||276M (JRE+jar)||36M|
Modules javafx.media and javafx.web are currently not supported for native compilation. The javafx.media module is responsible for adding the playback of media and audio content. The javafx.web module defines the WebView functionality.
In this step-by-step tutorial, we learned how to generate JavaFX native images. Liberica NIK can also be used to create tiny containers saving precious cloud resources. Give it a try!
Refer to our series of articles that explain how to use Liberica NIK with popular Java frameworks:
Generate a native executable with Spring Native — a version of Spring framework with built-in support for native images compilation
Create a microservice with Micronaut framework, designed especially for facilitating microservices development
Build a native image with Quarkus framework that natively supports GraalVM and MicroProfile APIs