【问题标题】:How to bundle a Java application to a Mac OS X *.app bundle?如何将 Java 应用程序捆绑到 Mac OS X *.app 捆绑包?
【发布时间】:2014-10-08 05:17:08
【问题描述】:

我正在尝试将我的 Java 应用程序捆绑到 Mac OS X .app 捆绑包中。我目前正在使用appbundler,我关注了Oracle's guide。 Ant 任务在 Netbeans 中运行良好,并且正确构建了相应的 .app 包(在 Windows 上)。但是当尝试将 .app 包执行到我的 MacBookPro (OS X 10.7.5) 时,我在日志中收到以下错误:

[0x0-0x72072].ch.lawsuite.core.Servitus: Error: Unable to access jarfile LawSuiteSE.jar

我已经检查了 .jar 文件的权限,并且为 main-jar 和 lib 文件夹中的所有 jar 设置了执行位。

在终端输入以下内容时,应用程序运行良好:

java -jar /Applications/Servitus.app/Contents/Java/LawSuiteSE.jar --installer

为了澄清,这是最终的文件夹结构:

Servitus.app
    |_Contents
        |_Java
            |_LawSuiteSE.jar
            |_lib
                |_lib1.jar
                |_lib2.jar
                    |_subfolder1
                        |_lib3.jar
                    |_subfolder2
                        |_lib4.jar
                |_etc...
            |_MacOS
                |_JavaAppLauncher
            |_PlugIns
            |_Resources
                |_en.lproj
                    |_Localizable.strings
                |_kplus.icns
        |_Info.plist
        |_PkgInfo

顺便说一句,我的应用程序有很多外部依赖项,都位于“lib”文件夹中,这些依赖项由可执行 main-jar 文件“LawSuiteSE.jar”的 MANIFEST.MF 文件中的 class-path 属性正确链接”。我需要在 appbundle-ant-task 中复制这些库,还是可以随后手动复制它们?

我也尝试在 MacBook Pro 上构建应用程序和对应的 .app 包,但同样的错误信息。

这是我的 Ant 任务:

<!-- Define the appbundler task -->
<taskdef name="bundleapp" classname="com.oracle.appbundler.AppBundlerTask"/>
<!-- Create the app bundle -->
<target name="bundle-macosx">
    <bundleapp outputdirectory="macosx"
        name="Servitus"
        displayname="Servitus"
        identifier="ch.lawsuite.core.Servitus"
        shortversion="1.0"
        applicationCategory="public.app-category.business"
        icon="src/ch/lawsuite/data/icons/gmbh/osx/kplus.icns"
        mainclassname="ch.lawsuite.core.Servitus">
        <classpath file="dist/LawSuiteSE.jar"/>
        <argument value="--installer"/>
    </bundleapp>
</target>

编辑:我同时用一个小的运行脚本 (start.sh) 替换了 Contents/MacOS 中的 JavaAppLauncher:

#!/bin/bash
java -Xms256m -XX:PermSize=128m -jar /Users/salocinx/Workspace/LawSuiteSE.app/Contents/Java/LawSuiteSE.jar --installer

然后我还将 Info.plist 中的键 CFBundleExecutable 的值从 JavaAppLauncher 替换为 start.sh.

现在它工作正常,但我如何使用 jar 可执行文件的相对路径?像“../Java/LawSuiteSE.jar”这样的东西不起作用,给我和以前一样的错误。是否有任何常量指向当前的应用程序文件夹,例如“$APP_ROOT”,以便脚本看起来像:

#!/bin/bash
java -Xms256m -XX:PermSize=128m -jar $APP_ROOT/Contents/Java/LawSuiteSE.jar --installer

有什么想法吗?

【问题讨论】:

  • 符号链接是否有效?通常,在 Windows 上构建时,符号链接会损坏。
  • 好的,我按照以下指南检查并更新了 MacBook Pro 上的符号链接:monkehworks.com/…。但我仍然没有工作。接下来我将尝试在 MacBook 上构建我的应用程序。
  • 构建整个项目并在 Mac 上捆绑包并没有帮助......仍然是同样的问题。

标签: java macos ant build jarbundler


【解决方案1】:

我是否需要在 appbundle-ant-task 中复制这些库

是的,您应该在classpath 元素中提及所有必需的库。然后捆绑器会将它们全部复制到捆绑包内的适当位置(只有在Contents/Java直接 的 JAR 文件会在捆绑包运行时进入类路径,子目录中的 JAR 将被忽略)。您还应该在主类名中使用点而不是斜线。

<bundleapp outputdirectory="macosx"
    name="Servitus"
    displayname="Servitus"
    identifier="ch.lawsuite.core.Servitus"
    shortversion="1.0"
    applicationCategory="public.app-category.business"
    icon="src/ch/lawsuite/data/icons/gmbh/osx/kplus.icns"
    mainclassname="ch.lawsuite.core.Servitus">
    <classpath file="dist/LawSuiteSE.jar"/>
    <classpath dir="lib" includes="*.jar" />
    <argument value="--installer"/>
</bundleapp>

编辑

现在它工作正常,但我如何使用 jar 可执行文件的相对路径

您可以使用dirname $0 获取您的捆绑包的Contents/MacOS 的路径,并从那里获取相对路径。您可能还应该明确引用公共 JRE,而不是依赖 java 在您的 PATH 上,因为这仅在目标计算机安装了 JDK 时才有效,而不是仅在JRE。安装 JDK 也会安装公共 JRE,所以在这种情况下也是安全的。

#!/bin/bash

SCRIPT_DIR="`dirname $0`"
exec "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java" \
  -Xms256m -XX:PermSize=128m -jar "$SCRIPT_DIR/../Java/LawSuiteSE.jar" --installer

【讨论】:

  • 您好伊恩,感谢您的建议。现在捆绑器将我的 lib 文件夹中的所有 .jar 文件复制并展平到 Contents/Java。我还将我的 MANIFEST.MF 调整为直接在 app-root 文件夹而不是 app-root/lib 中查找 .jar。但仍然是同样的问题。顺便提一句。真的没有办法保持lib文件夹中的文件夹结构吗?我的外部库本身对 lib 文件夹内明确定义的文件夹结构中的许多其他 jar-lib 有很大的依赖关系。提前致谢!
  • @salocinx 由捆绑器任务插入到包中的本机启动程序存根通过枚举包含在Contents/Java 目录(并且只有该目录,没有子目录)中包含的所有 jar 文件来创建它的类路径,并执行 mainclassname - 此行为在存根中硬编码,不可协商。
  • 感谢伊恩的快速回答。好吧,这些都是坏消息。是否有任何解决方法可以使用某种脚本或类似的东西从 .app-bundle 中启动我的应用程序?当直接使用“java -jar Servitus.jar --installer”启动时,我的应用程序基本上可以在 Mac 上正常运行,但我对 .app-bundle 真的很感兴趣...... :-) 还有什么想法吗?
  • @salocinx 你当然可以手动构建一个包,Contents/MacOS 中的主要“二进制”可以是一个委托给/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java 的 shell 脚本。这是我用于GATE 的方法,尽管在这种情况下它有点复杂,因为有第二级间接(它是一个跨平台工具,.app 捆绑包中的脚本委托给另一个 shell 脚本,它其他平台会直接调用)。
  • 嗨,伊恩,这正是我的意思。同时,我编写了一个小的 start.sh 脚本并将其与 Info.plist 中的 CFBundleExecutable 键链接。剩下的唯一问题是我需要在脚本中提供 .jar 可执行文件的完整路径,而相对路径不起作用......是否有一个占位符指向当前的 .app 文件夹,如 $APP_ROOT或类似的东西?请查看上面的原始问题,我添加了一个“编辑”部分来更详细地描述问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-29
  • 1970-01-01
  • 2015-12-04
  • 2014-02-09
  • 2014-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多