【问题标题】:Embedding a Java runtime into a sandboxed Cocoa Mac app将 Java 运行时嵌入到沙盒化的 Cocoa Mac 应用程序中
【发布时间】:2013-06-06 11:13:36
【问题描述】:

有人知道如何将 Java 运行时嵌入到 Mac Cocoa(沙盒)应用程序中,以便应用程序可以运行 .jar 文件,而无需用户单独安装 Java?

我们有一个 Cocoa 应用程序,我们通过 Mac App Store 以及我们自己的网站销售,它可以使用 Java 完成特定任务。这是一个写作应用程序,并且因为 .doc、.docx 和 .odt 的标准 NSText 导出器非常有限(不支持页眉、页脚、图像等),我们将其写入 RTF,然后使用基于 Java 的转换器(来自 Aspose. com) 将 RTF 转换为 .doc、.docx 或 .odt,具体取决于所选的导出格式。

我通过使用 NSTask 调用 /usr/bin/java 并运行捆绑的 .jar 文件来运行转换例程来做到这一点。这一切都很好——只要在用户的 Mac 上安装了 Java。如果未安装,我们的应用程序会询问用户是否愿意安装 Java 以从增强的转换器中受益,或者转而使用 NSText 有损转换器。如果用户选择安装 Java,我们调用 java_home --request 来调用 OS X 的 Java 安装程序。

但是,既然 Apple 已经结束(或正在结束)对 Java 的直接支持,这种方法就有问题了。在我们上次 Mac App Store 审查期间,我们被告知我们很快就需要停止询问用户是否要安装 Java。我读过 Apple 推荐的前进路线是将 Java 运行时环境嵌入到需要运行 Java 的 Cocoa 应用程序中。 (例如:http://lists.apple.com/archives/java-dev/2011/Jul/msg00038.html)

因此,在过去的几天里,我一直在研究如何在我的应用程序中嵌入 JRE,但我没有找到任何关于如何在任何地方这样做的说明 - 至少我不明白。几年前有人在这里问过类似的问题:

Bundling a private JRE on Mac OS X

但是,那里以及我在其他网站上找到的答案都是关于将 Java 应用程序捆绑为 Mac 应用程序,而不是在现有 Cocoa 应用程序中包含 JRE。 (虽然我承认我缺乏 Java 经验可能意味着我只是不明白如何为我的目的转换指令 - 让我离开 Xcode,我就离开了我的舒适区。)同样:https://wikis.oracle.com/display/OpenJDK/How+to+embed+a+.jre+bundle+in+your+Mac+app

似乎有几个应用程序已经做到了这一点(例如 Cyber​​duck),但还没有人记录这个过程。根据我的阅读,我认为我需要从 Oracle 的 JDK 或 OpenJDK 中获取 Java 虚拟机并将其包含在我的 Cocoa 应用程序中并从其中调用 java,但如果我这样做了,JVM 副本中的 Java 可执行文件不会被沙盒化,因此我的应用程序不会通过 MAS 审查过程。所以大概我需要以某种方式构建 JDK 的副本并将其沙箱化,很可能作为我更大的 Xcode 项目的一部分?我什至不知道从哪里开始;我猜现在还处于早期阶段,而且还没有多少 Mac 开发人员必须这样做。

有没有人有任何将 JRE 嵌入到 Cocoa 应用程序中的经验,这样应用程序就可以使用 NSTask 调用它?并且 JRE 是完全沙盒化的,因此可以被 Mac App Store 接受?或者,有没有人成功地创建了一个沙盒化的 Cocoa 应用程序,它运行一个 .jar 文件而不需要单独的 Java 安装?如果是这样,您愿意分享您是如何做到的吗?

(我向 Apple 提出了一个开发人员技术支持事件寻求帮助,但被告知他们根本无法提供帮助,因为 Java 现在被认为是第三方开发环境。)

非常感谢您对我可能错过的网页的任何建议或指示。

【问题讨论】:

  • 它看起来像你的是更一般的“如何在沙箱中使用辅助可执行文件”问题的一个特定案例。不是像codeotaku.com/journal/2012-10/… 中描述的那样为 JRE 指定权利并对其进行代码签名吗?
  • 非常感谢!我认为该链接正是我所需要的。 (它也解决了我在使用另一个可执行文件时遇到的问题。)所以,我的方法是:将 Oracle 网站上的 JRE 与我的应用程序捆绑在一起;在 10.6 及更低版本上,调用 OS X 的内置 Java 版本(假设它默认安装在 10.6- 上,而 Oracle 的 JRE 7 仅适用于 10.7+);在 10.7+ 上,调用应用程序内置的 JRE,并使用 codeotaku 链接中的方法将 Java 可执行文件沙箱化。手指交叉它通过了审查。再次感谢!

标签: java objective-c macos cocoa


【解决方案1】:

我不能确定,但​​我强烈怀疑,当那位 Apple 工程师说他们建议“嵌入”Java 运行时时,他并不是说“将单独的可执行文件捆绑到您的应用程序包中并在单独的进程中运行它” 就像他的意思是“在您自己的进程中启动 Java VM 并在该 VM 中运行您需要的东西。”这样做可能比在单独的进程中运行 Java 更麻烦,但这是可能的。

看看NSJavaVirtualMachine 类。如果用户没有安装 Java,它可能对您没有帮助,但想法是一样的 - 您只需构建一个包含 Java Runtime 的库,将其链接到您的主二进制文件,然后使用创建和管理 JVM JNI API。谷歌JNI_CreateJavaVM。

我在另一个问题 (Calling a Java class function from Cocoa with JNI) 中给出了一个简单的示例,即假脱机 JVM 并使用 JNI 调用 Java,尽管这是基于使用 Apple 捆绑的 JavaVM.framework,所以它不包括步骤构建您需要链接的库。不幸的是,我没有任何经验。

【讨论】:

  • 非常感谢您的回答。不过,NSJavaVirtualMachine 不是在 10.6+ 上弃用了吗?当然,我机器上的 NSJavaVirtualMachine.h 将所有内容标记为已弃用。不过,主要问题是我仍然需要在我的应用程序中捆绑 Java 运行时并将其沙箱化,所以我仍然面临同样的主要问题 - 幸运的是,我 认为 Bavarious 的链接应该帮助。再次感谢!
  • Bavarious' 链接是关于嵌入单独的可执行文件,您可以在单独的进程中但在同一个沙箱中运行这些可执行文件。我所说的是将 JRE 链接到应用程序的二进制文件并在进程内运行 Java 代码(显然在它们自己的线程上)。如果您将 JRE 链接到沙盒应用程序并在进程中执行代码,则 JRE 由于在沙盒进程中运行而被沙盒。你是对的 NSJavaVirtualMachine 已被弃用。
  • 您仍然可以使用嵌入式 JRE 附带的纯 JNI,即 JNI_CreateJavaVM...
【解决方案2】:

要回答您关于沙盒和辅助二进制文件的子问题,这不是问题。您只需将二进制文件标记为继承沙箱即可。

有一个像这样的.entitlements 文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.inherit</key>
    <true/>
</dict>
</plist>

并确保您在 Xcode 中有一个构建阶段,用于对 aux 二进制文件进行代码签名:

codesign --entitlements myjava.entitlements -s "${CODE_SIGN_IDENTITY}" java

【讨论】:

  • 您的回答帮助我解决了一个我一直在努力解决的问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-22
  • 2019-04-03
  • 1970-01-01
相关资源
最近更新 更多