Requirements#
Recently, I've started playing with penetration testing again, and many of the tools I use come as a .jar
file package. Although some can be opened directly by double-clicking, the icons in the Dock cannot be changed. Some can only run with Java 8, and I have to open the command line, switch JAVA_HOME, and then run the Java command to start it, which doesn't feel very elegant.
My previous approach was based on the automation tool Automator
provided by MacOS, which wraps a Bash script into an App. The script needs to have the JAVA_HOME path written correctly, and then run the .jar
file. However, this method is also not very elegant; it cannot customize the Dock icon, and there will be a spinning circle in the top menu bar. If several are opened, there will be multiple spinning circles, which is also not very elegant.
I Googled for solutions, but most tools are outdated versions, and some do not support the ARM
version. However, I found a GitHub project: universalJavaApplicationStub, which uses Bash as a launcher to start Jar files, but it can use the Bash script as a kernel to directly wrap the Jar file into a native MacOS App. Manual testing of the wrapped App program shows that it can run.
The general steps refer to this blog post, and the manual operation steps are as follows:
- Create folders like
/Applications/MyApp.app/Contents/{MacOS,Resources}
. - Write the
Info.plist
file, which defines the app name, version number, icon, and other meta information. - Place the
universalJavaApplicationStub
file, icon file, and Jar file into the corresponding folders.
In this way, an App is packaged, although the above steps are very simplified. In reality, the process is quite cumbersome, so it is better to wrap these steps into a command-line program that specifies configuration information through parameters, converting a Jar file into an App application with a single command.
Thus, I implemented jar2app in Golang. The basic principle is actually the above steps, but it is automated through code, requiring only a few parameters to be specified.
How it works#
jar2app has the following features:
- Convenience: Easy to configure, requiring only a few parameters to wrap a Jar file into a MacOS App application.
- Efficiency: Runs quickly, with packaging time usually not exceeding 1 second.
- Simplicity: Compact size, the packaged App size is roughly the same as the original Jar file, unlike Electron, which makes applications bulky.
- Usability: Simple installation, standalone binary file, can be installed and upgraded with a single command via brew.
Here are some notes
Because the structure of EXE files on Windows is completely different from that on MacOS, even though Golang can cross-compile across platforms, jar2app can only generate MacOS .app
format applications. Of course, you can also generate a MacOS App on Windows.
Considering the size of the packaged file, jar2app does not package the entire Java Runtime into the application, so before using jar2app, please install the corresponding Java version first. It is recommended to install multiple Java versions simultaneously to test whether the Jar file can run smoothly.
When packaging, if the $JAVA_HOME
is not set in the current environment variables, jar2app will automatically recognize the current environment's Java program's $JAVA_HOME
as the Java version for the App. If it cannot be recognized, the packaging will fail. If you need to specify a specific Java path, please refer to Usage.
Installation#
You can install it directly via brew.
brew install PriateXYF/tap/jar2app
jar2app is implemented in Golang. If you have a Go development environment, you can install it via go install
.
go install -v github.com/PriateXYF/jar2app@latest
Usage#
Parameter description:
Usage of jar2app:
-jar string
.jar file path [required]
-name string
app name [defaults to the same as the jar file name]
-icon string
.icns icon file path [defaults to empty icon]
-copyright string
app copyright information [defaults to Copyright 2025 virts]
-id string
app identifier information [defaults to app.virts]
-info string
app hint information [defaults to Made by virts.]
-v string
app version number [defaults to 1.0.0]
- Quick Start simplest usage
jar2app --jar MyApp.jar --icon MyApp.icns --name MyApp
- If you need to specify a specific JAVA_HOME
JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home/" jar2app --jar MyApp.jar --icon MyApp.icns --name MyApp
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home/
jar2app --jar MyApp.jar --icon MyApp.icns --name MyApp
- Full parameter example
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home/
jar2app --jar MyApp.jar --icon MyApp.icns --name MyApp --info "My App" --v "1.0.0" --id "app.virts" --copyright "Copyright 2025 virts"
If executed successfully, a corresponding .app
application will be generated in the current path, which can be opened directly by double-clicking. Enjoy it ~~~
Example#
Taking the ice shell Behinder
as an example, I will explain how to use jar2app and how to modify the configuration when additional parameters need to be added.
First, you can download the latest Jar package from the ice shell's Github Release page.
After downloading and extracting, you will find that it is not a single Jar file, but also contains other folders and files. These files can be processed later; for now, we only need to focus on the Behinder.jar
file.
Navigate to that folder in the command line, and I tried to run Behinder.jar
with the default Java version 23.0.1, but encountered an error. Switching to Java 8 allowed it to run normally.
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home/
java -jar Behinder.jar
Since it can run normally and the JAVA_HOME for executing the jar is configured correctly in this shell, I can directly use jar2app to package it. First, I randomly generated an icon using AI.
Then convert this icon to icns
format, recommended to use makeicns
for conversion.
brew install makeicns
makeicns -in behinder.png -out behinder.icns
Next, I can use jar2app to package the program.
jar2app --jar Behinder.jar --icon behinder.icns
At this point, if the configuration is correct, a Behinder.app application will be generated in the current path, but it still cannot be opened by double-clicking.
Since jar2app only places the individual Jar file in the corresponding application's Content/Java
path, it may not start due to missing some files or folders.
Move all contents from the extracted Behinder_v4.1.t00ls
into Behinder.app/Content/Java
, and try double-clicking the application again. It should start normally.
Drag Behinder.app
to the /Applications
folder, and the installation is successful. Enjoy it ~~~
Additionally, jar2app does not currently support adding extra parameters. If you need to specify additional parameters to run, please manually modify the universalJavaApplicationStub
script inside Behinder.app/Content/MacOS
, adding the required parameters at the end of the file.