The jpackage is a command-line tool introduced in Java 14 and helps create native installable packages (.exe, .msi, .dmg, .pkg, .deb, .rpm) for Windows, macOS, and Linux. Jpackage bundles Java applications along with a Java runtime (JRE) image, ensuring that end users do not need to install Java separately.
JPackage allows for various desktop integration features such as creating application shortcuts (system menu, desktop shortcut), file associations, etc.
1. Prerequisites
Before using jpackage, make sure we have the following available in the system:
- Java 14 or later (the latest version is recommended).
- The application is packaged as a fat jar file i.e. all necessary dependencies are bundled into the jar.
- On Linux and macOS, we must have the following packages:
- Windows: Wix 3.x
- Linux: dpkg (Debian-based) or rpm (RedHat-based)
- macOS: Xcode Command Line Tools
2. Steps to Use JPackage
There are two ways to use the jpackage tool:
- Using command line
- Using maven plugin
2.1. Using ‘jpackage‘ Command
To use the jpackage, for packaging an application we must make sure that the fat jar version of the application is already present.
Assuming that the fat jar name is: ‘myapp-jar-with-dependencies.jar‘: we can run the following command to create a .msi package for Windows installation. The type can be msi or exe.
jpackage \
--type exe \
--input . \
--name MyApp \
--main-jar myapp-jar-with-dependencies.jar \
--main-class com.example.Main \
--icon myapp.ico \
--win-menu \
--win-shortcut
Similarly, for macOS, we can run the following command. The type can be dmg or pkg.
jpackage \
--type dmg \
--input . \
--name MyApp \
--main-jar myapp-jar-with-dependencies.jar \
--main-class com.example.Main \
--icon myapp.icns \
--mac-package-identifier com.example.myapp \
--mac-sign
Similarly, for macOS, we can run the following command. The type can be deb or rpm.
jpackage \
--type deb \
--input . \
--name MyApp \
--main-jar myapp-jar-with-dependencies.jar \
--main-class com.example.Main \
--icon myapp.png \
--linux-package-name myapp
2.2. JPackage Maven Plugin
The most effective and recommended way is to use the jpackage maven plugin. Make sure you have set the JAVA_HOME environment variable pointing to the JDK which you want to use for jpackage.
The configuration has the following plugins:
- maven-compiler-plugin: for compiling the application using the configured JDK version.
- maven-assembly-plugin: for making the fat-jar from the application jar and all its dependencies.
- jpackage-maven-plugin: for packaging the application as an MSI installer.
...
<packaging>jar</packaging>
...
<properties>
<app.name>My Application Name</app.name>
<app.version>1.0.0</app.version>
<vendor.name>My Company Name</vendor.name>
<copyright>Copyright@2025</copyright>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>${maven.compiler.source}</maven.compiler.target>
<lombok.version>1.18.36</lombok.version>
</properties>
...
<build>
<finalName>${app.name}-${app.version}</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.github.akman</groupId>
<artifactId>jpackage-maven-plugin</artifactId>
<version>0.1.5</version>
<executions>
<execution>
<goals>
<goal>jpackage</goal>
</goals>
</execution>
</executions>
<configuration>
<name>${app.name}</name>
<appversion>${app.version}</appversion>
<copyright>${copyright}</copyright>
<vendor>${vendor.name}</vendor>
<mainjar>${app.name}-${app.version}-jar-with-dependencies.jar</mainjar>
<input>target/</input>
<mainclass>com.example.app.SwingApplication</mainclass>
<type>MSI</type>
<javaoptions>--enable-preview</javaoptions>
<dest>.</dest>
<icon>${project.basedir}/src/main/resources/app-icon.ico</icon>
<winconsole>false</winconsole>
<winmenu>true</winmenu>
<winshortcut>true</winshortcut>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.source}</target>
<release>${maven.compiler.source}</release>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.example.app.SwingApplication</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.github.akman</groupId>
<artifactId>jpackage-maven-plugin</artifactId>
<executions>
<execution>
<id>jpackage-installer</id>
<phase>verify</phase>
<goals>
<goal>jpackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
2.3. How to Run Jpackage Command
Once you configured all the required and optional properties, you can run the following maven command for building the fat jar and the package it as an installer.
$ mvn clean install
$mvn jpackage:jpackage
This will create the MSI installer file in the project base directory.
3. Important JPackage Parameters
The following is the list of important parameters to pass while packaging an installer file:
Parameter | Description |
---|---|
--input | Specifies the input directory where the application JAR is located |
--name | Sets the name of the application package |
--main-jar | Specifies the main application JAR file |
--main-class | Defines the main class with the main() method |
--type | Defines the package type (exe , msi , dmg , pkg , deb , rpm ) |
--icon | Sets the application icon file |
--app-version | Specifies the version of the application |
--win-menu | Creates a Windows Start Menu entry |
--win-shortcut | Creates a Windows desktop shortcut |
--linux-package-name | Sets the package name for Linux installers |
--mac-sign | Signs the macOS package (requires signing identity) |
4. Conclusion
jpackage is a very effective tool for creating native installers for Java desktop applications. It eliminates the need to have 3rd-party software for this specific purpose which involves extra cost and expertise.
By integrating the jpackage plugin in the maven build life-cycle, we can create an installer file as quickly as making a runnable jar file.
Happy Learning !!
Comments