如何优雅的将 Jar 打包成 Mac App

🤔 Requirements

最近又开始玩渗透了,用到的很多工具都是给一个 .jar 文件包,虽然有的也可以双击直接打开,但是 Dock 中的图标却不能更换,有的只能用 Java 8 运行,还得打开命令行,切换 JAVA_HOME ,然后再运行 Java 命令启动,感觉都不是很优雅。

我之前的操作是基于 MacOS 提供的自动操作 Automator 实现的,把一个 Bash 脚本封装成 App ,脚本里面要写好 JAVA_HOME 路径,然后运行 .jar 文件。但是这种方法也不是很优雅,不能自定义 Dock 图标,而且顶部菜单栏里面还会有个圈圈一直在转,如果开好几个就会同时有好几个圈圈,也不是很优雅。

Google 了一下解决方案,但是大多数工具都是上古的版本,有的不支持 ARM 版本,但是找到了一个 Github 项目 : universalJavaApplicationStub ,是通过 Bash 作为启动器启动 Jar 文件的,但是可以将 Bash 脚本作为内核,直接将 Jar 文件封装成原生 MacOS App ,手动测试封装好的 App 程序是可以运行的。

大概的步骤参考了 这篇博文 ,手工操作步骤如下:

  1. 创建 /Applications/MyApp.app/Contents/{MacOS,Resources} 等文件夹。
  2. 编写 Info.plist 文件,其中定义了应用名称、版本号、图标等 meta 信息。
  3. universalJavaApplicationStub 文件、图标文件、Jar 文件放入对应的文件夹中。

这样,一个 App 就算是打包好了,当然,上面的步骤是非常简化的,实际上操作的过程比较繁琐,所以不如把这些步骤封装成一个命令行程序,通过参数指定配置信息,一行命令将一个 Jar 文件转换为 App 应用程序。

于是,我用 Golang 实现了 jar2app ,大致原理其实就是上面的几个步骤,只不过是通过代码自动化实现的,只需要指定几个参数就可以了。

🥳 How it works

jar2app 具有以下特性:

  1. 便捷性 : 配置容易,只需几个参数即可将一个 Jar 文件封装成 MacOS App 应用程序。
  2. 高效性 : 运行快速,通常打包时间不会超过 1s 。
  3. 简洁性 : 体积小巧,打包后 App 大小与原始 Jar 文件大致相同,不像 Electron 会使应用程序变臃肿。
  4. 易用性 : 安装简单,独立二进制文件,可通过 brew 一键安装升级。

⚠️ 以下是注意事项

因为 Windows 下的 EXE 文件结构与 MacOS 完全不同,所以即使 Golang 可以跨平台交叉编译, jar2app 也只能生成 MacOS 的 .app 格式的应用程序,当然,你也可以在 Windows 上生成一个 MacOS 上的 App 。

考虑到打包后的文件大小, jar2app 并不会将整个 Java Runtime 都打包到应用程序中,所以在使用 jar2app 前,请 先安装好对应的 Java 版本 ,建议同时安装多个 Java 版本,以便测试是否能顺利运行 Jar 文件。

打包时,如果当前环境变量中未设置 $JAVA_HOMEjar2app 会自动识别当前环境 Java 程序的 $JAVA_HOME 作为 App 运行的 Java 版本,如果未识别出,则会打包失败。如果需要指定特定的 Java 路径,请参考 Usage 。

🚀 Installation

可以通过 brew 直接安装。

brew install PriateXYF/tap/jar2app

jar2app 通过 Golang 实现,如果你有 Go 开发环境,可以通过 go install 安装。

go install -v github.com/PriateXYF/jar2app@latest

📋 Usage

参数说明:

Usage of jar2app:
  -jar string
    	.jar 文件路径 [必填]
  -name string
    	app 名称 [默认与 jar 文件名相同]
  -icon string
    	.icns icon 文件路径 [默认为空图标]
  -copyright string
    	app 版权信息 [默认为 Copyright 2025 virts]
  -id string
    	app 标识符信息 [默认为 app.virts]
  -info string
    	app 提示信息 [默认为 Made by virts.]
  -v string
    	app 版本号 [默认为 1.0.0]
  • Quick Start 最简单的用法
jar2app --jar MyApp.jar --icon MyApp.icns --name MyApp
  • 如果需要指定特定的 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
  • 全参数示例
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"

如果成功执行,会在当前路径下生成对应名称的 .app 应用程序,可直接双击打开,😘 enjoy it ~~~

🙋🏻 Example

以冰蝎 Behinder 为例,说明一下如何使用使用 jar2app ,并且介绍当需要额外添加参数时,需要如何修改配置。

首先,可以到冰蝎的 Github Release 页面下载最新的 Jar 包。

下载解压后,发现并不是一个单一的 Jar 文件,还有其他的一些文件夹及文件,这些文件可以之后处理,目前只需要关注 Behinder.jar 这个文件。

命令行进入该文件夹,我尝试用默认的 Java 版本 23.0.1 运行 Behinder.jar ,发现有报错,切换到 Java 8 就可以正常执行了。

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home/
java -jar Behinder.jar

由于已经可以正常执行,且已在这个 shell 中配置好了可以正常执行 jar 的 JAVA_HOME ,就可以直接用 jar2app 打包了,先用 AI 随便生成一个图标。

然后将这个图标转为 icns 格式,推荐用 makeicns 转。

brew install makeicns
makeicns -in behinder.png -out behinder.icns

接下来就可以用 jar2app 打包程序了。

jar2app --jar Behinder.jar --icon behinder.icns

此时如果配置都正确的话会在当前路径下生成一个 Behinder.app 应用程序,但是双击仍然无法打开。

由于 jar2app 所做的操作仅会将当个 Jar 文件放入对应应用程序的 Content/Java 路径下,所以可能是由于部分文件或文件夹缺失导致无法启动。

把解压后得到的 Behinder_v4.1.t00ls 里的所有内容都移动到 Behinder.app/Content/Java 中,再次尝试双击应用程序,发现可以正常启动了。

Behinder.app 拖动到应用程序 /Applications 中,安装成功,😘 enjoy it ~~~


此外, jar2app 暂不支持添加额外参数,如果一定需要指定额外参数才能运行,请手动修改 Behinder.app/Content/MacOS 内的 universalJavaApplicationStub 脚本,在文件末尾添加需要的参数即可。

📚 Reference

评论