Creating Executables For JavaFX Applications

Here on Foojay, you can already find some great articles on how to create native executables from your JavaFX code:

Native Applications for Multiple Devices from a Single JavaFX Project with Gluon Mobile and GitHub Actions

JavaFX Templates for Desktop Applications

Let’s take a look in this article at the current state of what can be done with jpackage and GitHub Actions.

All the sources and workflow files used here can be found in the JavaPackageDemo repository.

General Configuration

JavaFX Launch File

A file is needed as an entry point to your JavaFX application.

A dedicated launcher file, such as, serves as the entry point for a Java application, handling essential setup tasks before starting the main program. This separation streamlines code management, keeping initialization logic distinct and making the application easier to maintain and expand.

For instance, if your main JavaFX application class is named MainApplication, create another Java file named and include the following code:

public class Launcher {
public static void main(String[] args) {


The process that is used here, is based on Gradle. Include the following code snippet in your build.gradle file to generate a standalone FatJar for your project.

A FatJAR is essential because it bundles an entire Java application with all its dependencies into a single file. This eliminates the hassle of managing external libraries separately, ensuring easy deployment and portability across various systems. It simplifies distribution, maintains version consistency, and allows the application to run independently without relying on external dependencies, making it an efficient and self-contained package for seamless execution.

task customFatJar(type: Jar) {
manifest {
attributes ‘Main-Class’: ‘YOUR.PACKAGE.Launcher’
archiveBaseName = ‘PackageDemoJAR’
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
with jar

task customFatJar(type: Jar): Defines a new task named customFatJar of type Jar, indicating that this task will generate a JAR file.

manifest {…}: Sets the Main-Class attribute in the JAR’s manifest file to point to the Launcher class, which serves as the entry point of your application.

archiveBaseName = ‘…’: Specifies the base name for the generated JAR file.

duplicatesStrategy = DuplicatesStrategy.EXCLUDE: Handles duplicate files encountered during the JAR creation process by excluding them.

from {…}: Collects all dependencies from the runtime classpath and includes them in the JAR. configurations.runtimeClasspath gathers the project’s runtime dependencies, and zipTree adds each dependency to the JAR.

with jar: Includes the existing JAR file (if any) generated by the default jar task along with the assembled JAR containing dependencies.

This customFatJar task amalgamates your project’s code and its dependencies into a single JAR file. Upon execution, the generated JAR file will be located in the following path: build/libs

To validate the functionality of your JAR file, execute it using the command: java -jar <path to your JAR file>. This command verifies the proper execution of your Java application encapsulated within the JAR.

Building Executables with jpackage

jpackage is generally included as part of the JDK starting from Java 14. However, in certain cases or older versions where it might not be bundled or available by default, you can manually download the JDK that includes jpackage from the official Oracle or OpenJDK website. Ensure you download a JDK version that explicitly mentions support for jpackage. After downloading and installing the JDK, you should have access to the jpackage tool in the JDK’s bin directory

To confirm whether jpackage is installed on your system, run the command jpackage –help on CMD or Terminal. If installed, this command will display the help information for the jpackage utility, confirming its presence and functionality.

$ jpackage –help
Usage: jpackage <options>

Sample usages:
Generate an application package suitable for the host system:
For a modular application:
jpackage -n name -p modulePath -m moduleName/className
For a non-modular application:
jpackage -i inputDir -n name
–main-class className –main-jar myJar.jar
From a pre-built application image:
jpackage -n name –app-image appImageDir

Creating a native executable application requires performing the build on the target platform. For each platform, the required additional steps and the jpackage command are explained.

GitHub Workflows

By using GitHub Actions, we can remove the need to have different platforms available to build native applications. Within the repository of the example project, workflows are provided for each platform which can be used as a guideline if you want to run the same process on your own machine.


Installing the WiX Toolset, version 3.0 or later for Windows is necessary. After completing the prerequisites, execute the following command:

jpackage –input <direcory of jar file> –name <name> –main-jar <main jar file > –main-class <main class> –type <type> –win-dir-chooser


jpackage –input build/ –name PackageDemo –main-jar <mPackageDemoJAR.jar > –main-class <com.heshanthenura.packagedemo.Launcher> –type msi –win-dir-chooser


For Linux, it’s required to install fakeroot. Run the following command to install fake root: apt-get install fakeroot -y.

For Red Hat Linux, it’s necessary to install rpm-build package. Run the following command to install rpm-build package: apt-get install fakeroot -y. When using yum (older versions of RHEL or CentOS): sudo yum install rpm-build.

After completing the prerequisites, execute the following command:

jpackage –input <direcory of jar file> –name <name> –main-jar <main jar file> –main-class <main class> –type <type>


For macOS, no additional installations are needed and you can immediately execute the following example command:

jpackage –input build/libs/ –name PackageDemo –main-jar PackageDemoJAR-1.0-SNAPSHOT.jar –main-class com.heshanthenura.packagedemo.Launcher –type dmg –dest build/macos/ –app-version 1.0 –vendor “Heshan Thenura”


Creating a native executable with JavaFX and jpackage for Windows, macOS, and Linux streamlines deployment across multiple operating systems.

Following a structured set of steps, developers can package Java applications into platform-specific native executables.

This process involves leveraging jpackage, which allows bundling the application, its dependencies, and a JRE into a standalone package, ensuring ease of installation and execution on various platforms.

Ultimately, this approach simplifies distribution, enhances user accessibility, and provides a consistent user experience across different operating systems for JavaFX applications.

The post Creating Executables For JavaFX Applications appeared first on foojay.