jpackage is a new tool with JDK 14 that generates native system installers for distributing your appliction.
It will create
.msi for Windows,
.dmg for Mac, and
.rpm for Linux distrubtions. This is ideal for GUI applications.
This guide will demonstrate how to use this tool to create system native installers for your applications.
jlink vs jpackage
jlink was introduced in Java 9 and
jpackage builds on top of
jlink and came with Java 14.
jlink under the hood.
jlink better, check out my tutorial How to Create Java Runtime Images with jlink.
You can manually perform the jlink step before running jpackage, otherwise jpackage automatically invokes jlink during the process
jlink generates the executable (e.g.
jpackage creates the installer for the executable (e.g.
Packaging non-modular apps
jpackage only supports JDK11+, you can still build traditional non-modular apps.
This is the simplest example to demonstrate how
You take an executable jar file, in this case
myapp.jar, and specify the class inside that you want to execute. The input directory tells
jpackage where to look for the JAR.
# input dir is where the main jar resides (`target/` typically with Maven projects) # main jar path should be relative to the input dir # main class is the executable class with a main() method jpackage -i ./target/ --main-class com.devdungeon.Main --main-jar myapp.jar
This generates a single standalone
.exe file that will install your application.
Packaging modular apps
With a modular app, you have a couple options. You could use
jlink to build the runtime image first. You could include your application and dependencies in this runtime, or you can use
Automatically generate a runtime image
jpackage will automatically run
jlink and generate a runtime with the modules needed. There is no need to run
jlink yourself unless you want something very custom. This example will generate the runtime and installer package with your module.
jpackage \ --module-path .;target/my.jar \ --module mymodule/com.devdungeon.Main \ --add-modules java.desktop,mymodule \
Use a custom runtime image
If you already have a runtime image with the modules in it, you can simply tell
jpackage to use the runtime image you want with the
Specify the main class with the
To learn how to create a custom runtime, check out my tutorial How to Create Java Runtime Images with jlink.
Here is an example of packaging an existing runtime to run a specific class.
jpackage \ --runtime-image my-custom-jre-with-app \ --module mymodule/com.devdungeon.Main
Add a startup splash screen
# APPDIR resolves to app final install dir --java-options '-splash:$APPDIR/splash.png'
Associating file extensions with your app
For example, if I wanted to create a file extension
.dano for my application.
You can specify the following things for your custom file type:
- the file icon
- the mime-type you want to use
- the file extension
Common Windows options
Here are a few useful options when generating a Windows installer.
Let users choose the install directory
Creating a console launcher
# Create a console launcher for CLI applications --win-console
Creating Start menu entry
# Add app to start menu --win-menu # defaults to "Unknown" folder without --win-menu-group --win-menu-group <name>
# Create desktop shortcut --win-shortcut
Install for user instead of system-wide
After reading this guide, you should understand how to use
jpackage to generate a system-native installer for a Java application whether it is module or non-modular.