简体   繁体   English

将Java运行时嵌入到沙盒Cocoa Mac应用程序中

[英]Embedding a Java runtime into a sandboxed Cocoa Mac app

Does anybody know how to embed a Java runtime into a Mac Cocoa (sandboxed) app so that the app can run a .jar file without the user having to install Java separately? 有没有人知道如何将Java运行时嵌入到Mac Cocoa(沙盒)应用程序中,以便应用程序可以运行.jar文件而无需用户单独安装Java?

We have a Cocoa application that we sell through the Mac App Store as well as on our own site which can use Java for a specific task. 我们有一个Cocoa应用程序,我们通过Mac App Store以及我们自己的站点销售,可以使用Java来执行特定任务。 It's a writing app, and because the standard NSText exporters for .doc, .docx and .odt are very limited (not supporting headers, footers, images etc), we write out to RTF and then use Java-based converters (from Aspose.com) to convert the RTF to .doc, .docx or .odt, depending on the chosen export format. 它是一个编写应用程序,因为.doc,.docx和.odt的标准NSText导出器非常有限(不支持页眉,页脚,图像等),我们写出RTF然后使用基于Java的转换器(来自Aspose。 com)将RTF转换为.doc,.docx或.odt,具体取决于所选的导出格式。

I do this by by using NSTask to call on /usr/bin/java and run a bundled .jar file that runs the conversion routines. 我通过使用NSTask调用/ usr / bin / java并运行运行转换例程的捆绑.jar文件来实现此目的。 This all works beautifully--as long as Java is installed on the user's Mac. 这一切都很好用 - 只要Java安装在用户的Mac上。 If it's not installed, our app asks the user if he or she would like to install Java to benefit from the enhanced converters, or instead fall back on the NSText lossy converters. 如果没有安装,我们的应用程序会询问用户是否要安装Java以从增强型转换器中受益,或者反过来使用NSText有损转换器。 If the user chooses to install Java, we call java_home --request to invoke OS X's Java installer. 如果用户选择安装Java,我们调用java_home --request来调用OS X的Java安装程序。

However, now that Apple has ended (or is ending) direct support for Java, this approach is problematic. 但是,既然Apple已经结束(或即将结束)对Java的直接支持,这种方法就存在问题。 During our last Mac App Store review, we were told that we would soon need to stop asking the user if he or she wanted to install Java. 在我们上一次Mac App Store审核期间,我们被告知我们很快就会停止询问用户是否要安装Java。 I have read that Apple's recommended route going forward is to embed a Java Runtime Environment into Cocoa applications that need to run Java. 我已经读到Apple推荐的路线是将Java Runtime Environment嵌入到需要运行Java的Cocoa应用程序中。 (Eg: http://lists.apple.com/archives/java-dev/2011/Jul/msg00038.html ) (例如: http//lists.apple.com/archives/java-dev/2011/Jul/msg00038.html

Over the past few days, I've therefore been researching how I can go about embedding a JRE in my app, but I haven't found any instructions on how to do so anywhere - nothing that I understand, at least. 在过去的几天里,我一直在研究如何在我的应用程序中嵌入JRE,但是我没有找到任何关于如何在任何地方执行此操作的说明 - 至少我没理解。 Someone asked a similar question here a couple of years ago: 几年前有人问过类似的问题:

Bundling a private JRE on Mac OS X 在Mac OS X上捆绑私有JRE

However, the answers there, and on other sites I've found, are all about bundling a Java application as a Mac application, not about including a JRE with an existing Cocoa application. 然而,那里和我发现的其他网站上的答案都是关于将Java应用程序捆绑为Mac应用程序,而不是将JRE与现有的Cocoa应用程序包含在一起。 (Although I accept that my lack of experience with Java may mean that I just don't understand how to convert the instructions for my purposes - take me out of Xcode and I'm out of my comfort zone.) Likewise: https://wikis.oracle.com/display/OpenJDK/How+to+embed+a+.jre+bundle+in+your+Mac+app (虽然我接受我缺乏Java经验可能意味着我只是不明白如何为我的目的转换指令 - 带我离开Xcode并且我不在我的舒适区。)同样: https:/ /wikis.oracle.com/display/OpenJDK/How+to+embed+a+.jre+bundle+in+your+Mac+app

It seems that a couple of applications have done this (eg Cyberduck), but no one has documented the process yet. 似乎有几个应用程序已经这样做了(例如Cyber​​duck),但还没有人记录过这个过程。 From what I've read, I think I need to either grab the Java Virtual Machine from Oracle's JDK or OpenJDK and include that in my Cocoa app and call on java from within that, but if I did so, the Java executables within the copy of the JVM wouldn't be sandboxed, so my app wouldn't get through the MAS review process. 从我读过的内容来看,我认为我需要从Oracle的JDK或OpenJDK中获取Java虚拟机,并将其包含在我的Cocoa应用程序中并从中调用java,但如果我这样做,那么副本中的Java可执行文件JVM不会被沙盒化,因此我的应用程序无法通过MAS审核流程。 So presumably I need to somehow build a copy of the JDK and sandbox it, most likely as part of my larger Xcode project? 所以我可能需要以某种方式构建JDK和沙箱的副本,最有可能是我的大型Xcode项目的一部分? I'm not even sure where to start; 我甚至不确定从哪里开始; I'm guessing it's still early days and that not many Mac developers have had to do this yet. 我猜它还处于早期阶段,并没有多少Mac开发人员必须这样做。

Has anyone got any experience of embedding a JRE into a Cocoa application in such a way that the app can just call on it using NSTask? 有没有人有过将JRE嵌入到Cocoa应用程序中的经验,应用程序只能使用NSTask调用它? And in such a way that the JRE is fully sandboxed and thus acceptable by the Mac App Store? 并且以这种方式使JRE完全沙箱化并因此被Mac App Store接受? Or, has anyone successfully created a sandboxed Cocoa app that runs a .jar file without needing a separate Java installation? 或者,是否有人成功创建了一个运行.jar文件的沙盒Cocoa应用程序,而无需单独的Java安装? If so, would you be willing to share how you did it? 如果是这样,你愿意分享你是如何做到的吗?

(I took out a developer tech support incident with Apple asking for help on this, but was told that they couldn't help at all given that Java is now considered a third-party development environment.) (我向Apple发起了一个开发者技术支持事件,请求帮助,但有人告诉他们,鉴于Java现在被认为是第三方开发环境,他们根本无法帮助。)

Many thanks in advance for any suggestions or pointers to web pages I may have missed. 非常感谢您对我可能错过的网页的任何建议或指示。

I can't be sure, but I strongly suspect that when that Apple engineer says they suggest "embedding" the Java runtime, he doesn't mean "bundle a separate executable into your app bundle and run it in a separate process" so much as he means "spin up a Java VM within your own process and run what you need to in that VM." 我无法确定,但我强烈怀疑,当Apple工程师表示他们建议“嵌入”Java运行时时,他并不是说“将一个单独的可执行文件捆绑到您的应用程序包中并在一个单独的进程中运行”这么多因为他的意思是“在您自己的流程中启动Java VM并在该VM中运行您需要的东西。” It's arguably more cumbersome to do this than it is to run Java in a separate process, but it is possible. 这可能比在单独的进程中运行Java更麻烦,但这是可能的。

Have a look at the NSJavaVirtualMachine class. 看看NSJavaVirtualMachine类。 It may not help you if the user doesn't have Java installed, but the idea would be the same - you would just build yourself a library containing the Java Runtime, link it into your main binary, then create and manage the JVM using the JNI API. 如果用户没有安装Java,它可能没有帮助,但想法是相同的 - 你只需构建一个包含Java Runtime的库,将其链接到主二进制文件,然后使用它创建和管理JVM JNI API。 Google for JNI_CreateJavaVM . Google for JNI_CreateJavaVM

I gave a quick example of spooling up a JVM and calling into Java using JNI in another question ( Calling a Java class function from Cocoa with JNI ), although that was predicated on using the Apple-bundled JavaVM.framework, so it doesn't include steps on building the library you would need to link. 我给出了一个快速示例,假设在另一个问题中调用 JVM并使用JNI调用Java(使用JNI 从Cocoa调用Java类函数 ),尽管这是基于使用Apple捆绑的JavaVM.framework,因此它没有包括构建您需要链接的库的步骤。 I don't have any experience with that, unfortunately. 不幸的是,我对此没有任何经验。

To answer your sub-question about sandbox and aux binaries, that's not a problem. 要回答关于沙盒和辅助二进制文件的子问题,这不是问题。 You just have to mark the binary as inheriting the sandbox. 您只需将二进制文件标记为继承沙箱即可。

Have an .entitlements file like this: 有这样的.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>

And make sure you have a build phase in Xcode that codesigns the aux binary: 并确保在Xcode中有一个构建阶段,用于编码辅助二进制代码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM