将 JAR 转换为完整的 MacOS 应用程序
目录
几年前,我开发了一个小型的 Kotlin GUI 来帮助我批量重命名文件。实际上,我用 不同的 JVM 框架 创建了它,以比较它们的相对优缺点。无论如何,直到上周我都没怎么用过它。然后,我惊讶地发现它无法重命名网络卷,尽管过去是可以的。在这篇简短的文章中,我旨在描述这个问题及其解决方案。
问题
启动 UberJAR 时,我看不到网络卷。如果我在字段中输入路径,也看不到任何子节点。我在网上搜索了解决方案,提到需要授予应用程序“本地网络”权限:设置 > 隐私与安全性 > 本地网络。我尝试将 Java SDK 或 UberJAR 添加到列表中,但没有找到方法。
[LOADING...]
解决方案
解决方案很简单:从 UberJAR 创建一个标准的 MacOS 应用程序。最简单来说,MacOS 应用程序只是一个具有特定结构的文件夹。你可以手动复制它,但我很懒,而且有现成的工具。jpackage 就是这样一个工具。jpackage 是我了解过、为之兴奋、用过一次然后直到下次需要才会想起的工具之一。计数加一。
起初,我天真地像这样使用 jpackage:
- 设置值
- 要包含的文件夹
- 应用名称
- UberJAR 的路径
它有效并生成了一个 MacOS 应用。我们可以启动生成的应用,操作系统会询问是否允许本地网络访问。完成。
然而,jpackage 将整个 target 文件夹的内容复制到了应用中。它不仅包含原始 JAR、类,还包含其余的内容。
改进构建
我决定改进 Maven 构建,而不是手动调用 jpackage。
第一步是将 UberJAR 移动到一个空文件夹,以便我们可以设置 jpackage 的 input。
下一步实际上是找到一个封装了 jpackage 的 Maven 插件。我找到了 org.panteleyev:jpackage-maven-plugin。以下是使用方法:
- 应用名称
- 指向上一步创建的文件夹
- 主 JAR 的路径
- 设置值
请注意,这些参数模仿了命令行选项。
最后润色
有两个最后润色点:版本和应用的大小。
让我们从版本开始。上述配置使用了 ${project.version}。如果它带有 -SNAPSHOT 后缀,构建就会失败,因为 Mac 应用版本必须遵循 major.minor.bugfix 模式。为了解决这个问题,我们可以利用 build-helper-maven-plugin。它提供了几个目标(goal),包括 parse-version,它可以将 Maven 版本解构为几个属性。
我们可以用以下内容替换版本行:
第二个改进是最终应用的大小。在我的机器上,上述配置生成的应用大小为 160MB。对于基于 JVM 的应用来说,这并不令人担忧,但也算不上好。好在 jpackage 底层利用了 jlink;jlink 创建一个自定义的 JRE。该应用是自包含的。
jpackage 使用所有配置的模块,或者默认使用所有模块。不好的是,我们没有配置任何模块。通过仅添加必要的模块,我们可以将应用大小减少一半,降至 82MB。
此时,你可以将应用移动到 Mac 的 Applications 文件夹中。你还可以使用图标等进一步自定义它。对我来说,这已经足够满足我的需求了。
结论
在这篇文章中,我们从一个由于当前 MacOS 安全模型而无法重命名远程卷上文件的 UberJAR 开始。为了使其工作,我们将 UberJAR 封装在一个原生的 MacOS 应用中。然后,我们通过使用显式模块将大小减少了一半,从而改进了这种情况。
这篇文章的完整源代码可以在 GitHub 上找到。
延伸阅读:
最初于 2025 年 1 月 25 日发布在 A Java Geek
本文 从 JAR 到完整的 MacOS 应用 首次出现在 foojay 上。