应用程序在Mac OS X上使用的是Apple的Java 6而不是Oracle的Java 7?

35

我正在使用安装了 Oracle Java 7 的 Mac OS X 测试我的应用程序。但是它却使用了 Apple 的 Java 6,而不是 Oracle Java 7。系统默认的 java -version 命令输出显示为 7

我尝试了许多网站上提到的方法,但是无法解决这个问题。

JAVA_HOME 也已正确设置。

我只是在 Mac 上进行测试,真的需要一些帮助。

当我通过选择 JRE 7 在 Eclipse 中运行时,它可以正常运行。因此,应用程序没有问题。我在 Mac OS X 上缺少某些东西。

我的 Java 系统环境如下:

  • OS X 版本

    10.8

  • /usr/libexec/java_home -V

    Matching Java Virtual Machines (3):
    1.7.0_12, x86_64: "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_12.jdk   
    1.6.0_37-b06-434, x86_64: "Java SE 6" /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
    1.6.0_37-b06-434, i386: "Java SE 6" /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
    
    /Library/Java/JavaVirtualMachines/jdk1.7.0_12.jdk/Contents/Home
    
  • /usr/libexec/java_home

  • /Library/Java/JavaVirtualMachines/jdk1.7.0_12.jdk/Contents/Home
    
  • echo $JAVA_HOME

    /Library/Java/JavaVirtualMachines/jdk1.7.0_12.jdk/Contents/Home/
    
  • JAVA_ARCH未设置

  • /Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java -version

    java version "1.7.0_12-ea"
    
  • ls /Library/Java/JavaVirtualMachines

    列出在Mac上安装的Java虚拟机。
    jdk1.7.0_12.jdk
    
  • /System/Library/Frameworks/JavaVM.framework/Commands/java -version

  • java version "1.6.0_37"
    
    我猜我的当前JDK指向了错误的东西。

还有,你如何执行这个应用程序? - Armand
@Alison 我是用用户方式完成的...不是通过Shell,而是双击完成的。 - amod
为什么不直接使用绝对路径来运行你的应用程序,例如 /Library/Java/JavaVirtualMachines/jdk1.7.0_10.jdk/Contents/Home/bin/java? - Jintian DENG
请帮助这个问题获得更多关注。即使已经提供了悬赏,它仍然没有得到足够的关注。 - amod
@amod0017,你知道JAVA_HOME是全大写的,不像你写的Java_Home。 - Uwe Günther
显示剩余15条评论
5个回答

90

问题

您的 Mac OS X 应用程序包是使用与 Oracle Java 7 包不兼容的应用程序打包程序创建的。例如,您使用的可能是由 Apple 提供的 Jar Bundler,它仅适用于 Apple 的 Java 6 系统包。

Apple 已经放弃了对 Java 的支持,从 Java 7 及更高版本开始不再作为集成系统包提供。因此,您必须选择 Oracle Java 7 的第三方包和它们的应用程序包解决方案。这样可以在 Mac OS X 10.7.3 及以上版本上创建和部署基于 Oracle Java 7 的应用程序包。

您面临的根本技术问题是基于 Apple 原生的 Objective-C 代码的 JavaAppLauncher 二进制文件以及它在 Info.plist 中使用的格式仅适用于 Apple 的 Java 6 系统包,而来自 Oracle 的 JavaAppLauncher + Info.plist 组合仅适用于 Oracle 的 Java 7 包。

由于您正在使用支持 Apple 的 Java 6 系统包的 JavaAppLauncher,它将始终选择安装在 Mac 上的 Apple Java 6 系统包。

有一个视频,其中 Oracle Java 平台在 Mac OS X 上的主要工程师 Scott Kovatch 对 Oracle Java 7 的应用程序打包如何运作进行了详细讲解。

解决方案

要基于以下版本的 Mac OS X(10.7.3 及以上版本)创建应用程序包:

您必须使用 Oracle 的应用程序打包程序:

使用 Oracle 的应用程序打包程序,您现在可以选择在此处使用默认的安装在 Mac 上的 Oracle Java 7 系统包运行打包的应用程序:

  • /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/

或者在您的打包应用程序中内置 Oracle Java 7 JRE。

  • MyJavaMacOSXApp.app/Contents/PlugIns/

Note: 两种方法各有利弊,但如果您想将捆绑的应用程序上传到苹果应用商店,则需要使用自己的JRE执行最后一种方法。

需要完成的任务

  • 下载appbundler-1.0.jar,并将其移动到<project>/lib/appbundler-1.0.jar
  • 在您的<project>/build.xml文件中添加以下内容:

    <property environment="env" />
    
    <taskdef 
        name="bundleapp" 
        classname="com.oracle.appbundler.AppBundlerTask" 
        classpath="lib/appbundler-1.0.jar" />
    
    <target name="bundle">
        <bundleapp 
            outputdirectory="dist" 
            name="MyJavaMacOSXApp" 
            displayname="My Java Mac OS X App" 
            identifier="com.example.MyJavaMacOSXApp" 
            shortversion="1.0"
            applicationCategory="public.app-category.developer-tools"
            mainclassname="com.example.MyJavaMacOSXApp">
            <runtime dir="${env.JAVA_HOME}" />
            <classpath file="dist/MyJavaMacOSXApp.jar" />
        </bundleapp>
    </target>
    

    注意:你需要用你的应用数据替换MyJavaMacOSXApp。你可以在这里找到一些额外的AppBundlerTask选项,因为此例仅展示了其最简单的工作方式。

    在使用 ant bundle 运行 bundle 目标之后,你将在 <project>/dist 目录中找到 MyJavaMacOSXApp.app

    元素<runtime dir="${env.JAVA_HOME}" />是什么意思?

    内联 Oracle Java 7 Package (JRE)

    上面的 Ant 目标将 Oracle Java 7 Package (JRE) 从您的JAVA_HOME复制到

    • MyJavaMacOSXApp.app/Contents/PlugIns

    因此,应用程序包完全自包含,根本不需要在目标系统上安装 Oracle Java 7 Package (JRE)。正如您可以在下面截图中看到的那样,这是一个已部署的 MyJavaMacOSXApp.app

    MyJavaMacOSXApp Inline JRE

    连接默认的 Oracle Java 7 Package (JRE)

    如果要使用应用程序包目标 Mac 上默认的 Oracle Java 7 Package (JRE),则必须从bundle任务中删除元素<runtime dir="${env.JAVA_HOME}" />。正如您可以在下面截图中看到的那样,这是一个已部署的 MyJavaMacOSXApp.app

    MyJavaMacOSXApp Inline JRE

    MyJavaMacOSXApp.java 的来源

    package com.example;
    
    import java.awt.*;
    import javax.swing.*;
    
    public class MyJavaMacOSXApp extends JPanel {
    
        public MyJavaMacOSXApp() {
            JLabel versionLabel = new JLabel("java.version=" + System.getProperty("java.version"));
            JLabel homeLabel = new JLabel("java.home=" + System.getProperty("java.home"));
            setLayout(new BorderLayout());
            add(versionLabel, BorderLayout.PAGE_START);
            add(homeLabel, BorderLayout.PAGE_END);
        }
    
        private static void createAndShowGUI() {
            JFrame frame = new JFrame("MyJavaMacOSXApp");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            MyJavaMacOSXApp newContentPane = new MyJavaMacOSXApp();
            newContentPane.setOpaque(true); 
            frame.setContentPane(newContentPane);
            frame.pack();
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGUI();
                }
            });
        }
    }
    

    如果我的应用程序有多个jar文件怎么办?

    只需添加尽可能多的<classpath file="dist/additional.jar" />条目。

    注意:在捆绑任务中,<classpath>元素的顺序在捆绑后的应用程序运行时不会保留。 java.class.path是由本机JavaAppLauncher在运行时从MyJavaMacOSXApp.app/Contents/Java目录中读取*.jar


    仅为完整起见,这是Info.plist的外观:

    <?xml version="1.0" ?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
        <dict>
            <key>CFBundleDevelopmentRegion</key>
            <string>English</string>
            <key>CFBundleExecutable</key>
            <string>JavaAppLauncher</string>
            <key>CFBundleIconFile</key>
            <string>GenericApp.icns</string>
            <key>CFBundleIdentifier</key>
            <string>com.example.MyJavaMacOSXApp</string>
            <key>CFBundleDisplayName</key>
            <string>My Java Mac OS X App</string>
            <key>CFBundleInfoDictionaryVersion</key>
            <string>6.0</string>
            <key>CFBundleName</key>
            <string>MyJavaMacOSXApp</string>
            <key>CFBundlePackageType</key>
            <string>APPL</string>
            <key>CFBundleShortVersionString</key>
            <string>1.0</string>
            <key>CFBundleSignature</key>
            <string>????</string>
            <key>CFBundleVersion</key>
            <string>1</string>
            <key>NSHumanReadableCopyright</key>
            <string></string>
            <key>LSApplicationCategoryType</key>
            <string>public.app-category.developer-tools</string>
            <key>JVMRuntime</key>
            <string>jdk1.7.0_17.jdk</string>
            <key>JVMMainClassName</key>
            <string>com.example.MyJavaMacOSXApp</string>
            <key>JVMOptions</key>
            <array>
            </array>
            <key>JVMArguments</key>
            <array>
            </array>
        </dict>
    </plist> 
    

    本答案基于以下重要文档:

    1. http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/packagingAppsForMac.html
    2. http://java.net/projects/appbundler/pages/Home
    3. http://java.net/downloads/appbundler/appbundler.html
    4. http://intransitione.com/blog/take-java-to-app-store/
    5. http://www.parleys.com/#st=5&id=2891&sl=37

    另外,还有一个维护良好的appbundler分支,带有许多更多的特性和bugfixes。


2
@amod0017 我修改了答案帖子。您可以在“如果我的应用程序有多个jar文件怎么办?”下找到它。Oracle的AppBundler将保留所有*.jar文件在“MyJavaMacOSXApp.app/Contents/Java”目录中。我希望这个答案对您有所帮助,如果您认为这是解决您问题的答案,我会很感激您将此答案帖子标记为您问题的答案(绿色勾号)。 - Uwe Günther
1
使用此帖子中描述的标准方法,并建议Oracle为在Mac OS X 10.7.3+上进行Java 7应用程序包的方式,您现在拥有一个*.app软件包。只需将此应用程序包粘贴到标准的Mac OS X磁盘映像(也称为*.dmg文件)中并将其发送给客户即可。详细信息可以在此找到:https://dev59.com/u3VD5IYBdhLWcg3wE3Xz - Uwe Günther
1
@amod0017,我感谢你的慷慨奖励和采纳答案!看起来你的问题可以填写一本关于在Mac OS X上开发Java的书的章节。尽管如此,我认为如果你按照这里描述的方式创建一个应用程序包 - 你就可以着手构建一个dmg文件以部署到最终用户了。自从第一天起,我的电子邮件地址就公开在我的个人资料中。只需检查一下是否能在那里找到它,如果找不到,请告诉我。 - Uwe Günther
2
@lance-roberts 感谢您修复我的帖子中的错别字。我喜欢评论,尤其是如果是这样的评论。 - Uwe Günther
1
在尝试在Mac OS X Yosemite中执行这些步骤时,我遇到了以下错误:构建失败 NetBeansProjects/MyJavaMacOSXApp/build.xml:89: java.nio.file.NoSuchFileException: NetBeansProjects/MyJavaMacOSXApp/Info.plist是否应该在某个地方有一个Info.plist文件? - ziggurism
显示剩余8条评论

4

应用所需的Java版本可能在应用程序的元数据中指定。如果您右键单击应用程序并选择 显示包内容 ,然后浏览到 Info.plist 文件,您应该会找到定义应用程序将使用的JVM的条目。例如:

    <key>JVMVersion</key>
    <string>1.5</string>

如果应用程序请求,OSX 可能选择使用较低版本的 JVM。


是的,在 info.plist 中有 1.4+ 的版本。将其更改为 1.7 后,弹出一个窗口显示 Java 1.7 版本不兼容。但是,java -version 命令可以正常工作。 - amod
增加进一步操作。它要求设置Java首选项,但自从我重新安装Java以来,我无法获得该选项(苹果已将其删除)。请告诉我是否可能有其他解决方法。 - amod
根据http://developer.apple.com/library/mac/#documentation/Java/Reference/Java_InfoplistRef/Articles/JavaDictionaryInfo.plistKeys.html#//apple_ref/doc/uid/TP40001969,您可以将其更改为1.6+并尝试一下。 - Jintian DENG
我把它改成了1.7,但它没有起作用。请检查我的先前评论。 - amod
1
@sixlettervariables 像我在答案中提到的那样,有两种不同的本地 JavaAppLaunchers,一种来自苹果公司,也称为 Jar Bundler,它仅适用于苹果的 Java 系统包。苹果最新的版本是 1.6.0_43,没有适用于 Java 7 的版本。另一种是来自 Oracle 的 AppBundlerTask,它仅适用于 Oracle 的 Java 系统包。Oracle 最早能够与 Mac OS X 10.7.3 及以上版本配合使用的 Java 版本是 1.7.0_04。希望这能消除任何歧义和疑虑。除了这两个官方版本外,还有一些第三方方法可供选择。 - Uwe Günther

4

你的系统并不是最新的。我并不是说这导致了你的问题。但为了安全起见,我建议你升级到最新版本。

  1. 通过系统更新将您的系统升级到Mac OS X 10.8.2
  2. 从苹果公司安装全新的JRE 1.6.0_43,即Java for OS X 2013-002
  3. 从苹果公司安装全新的JDK 1.6.0_43,即Java for OS X 2013-002 Developer Package Mar 4, 2013。要获取Apple JDK,您需要使用Apple ID (免费的开发者帐户)登录此处,并搜索“Java for OS X 2013-002 Developer Package”。不幸的是,该程序没有直接的链接。
  4. 删除过时的Oracle JDK:sudo rm -rf /Library/Java/JavaVirtualMachines/jdk1.7.0_12.jdk。注意: 这是安全的,因为在下一步中我们将安装当前的Oracle JDK 1.7.0_17。
  5. 下载并安装Mac OS X版Oracle JDK 1.7.0_17。注意:这也包括来自Oracle的JRE 1.7.0_17。
  6. 重新启动计算机。

完成上述步骤后,请再次输出以下内容:

  1. 您使用的是哪个OS X版本?
  2. 命令/usr/libexec/java_home -V输出了什么?
  3. 命令/usr/libexec/java_home输出了什么?
  4. 命令echo $JAVA_HOME输出了什么?
  5. 命令echo $JAVA_ARCH输出了什么?
  6. 命令/Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java -version输出了什么?
  7. 命令ls /Library/Java/JavaVirtualMachines输出了什么?
  8. 命令/System/Library/Frameworks/JavaVM.framework/Commands/java -version输出了什么?

只需在原始问题中记录您所做的步骤和努力,以反映您的进展。

更新: 解决方案是使用 Oracle 的AppBundlerTask创建 Mac OS X 应用程序包。有关详细信息,请参见我在此处的其他答案:https://dev59.com/QmUq5IYBdhLWcg3wF8dQ#15271448


我开始整个事情,稍后会回复你。 - amod
2
@amod0017 请看一下我在这里的另一个答案:https://dev59.com/QmUq5IYBdhLWcg3wF8dQ#15271448 看起来这个可以解决你的问题。 - Uwe Günther

1
尝试安装这个:

http://support.apple.com/kb/dl1572

InteliJ工作得很好,而我仍在使用Java SE 7,例如NetBeans。

java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)

我有一个第三方应用程序,在升级到El Capitan后无法工作。上面的解决方案现在使它在El Capitan中工作。我宁愿让它与新的Java版本正常工作,但这也可以 :) - Ketan

1

编辑: Uwe的回答针对使用AppLauncher的原问题是完全正确的。我最初阅读问题时认为它涉及在OSX上使用Java 6和Java 7时的命令行问题。原问题上的评论表明我错了。无论如何,任何遇到命令行问题的人都可能会发现下面的解决方案更简单。

原文: 我的情况似乎与原问题一样:命令行上完美地运行Java 1.7但mvn失败并抱怨1.6,使用sbt和IntelliJ进行的编译工作正常。只有在使用mvn编译第三方项目时才开始出现问题。

我发现以下方法很有效且简单:

http://www.jayway.com/2013/03/08/configuring-maven-to-use-java-7-on-mac-os-x/

我只需要在.profile文件中包含以下内容:

export JAVA_HOME=`/usr/libexec/java_home -v 1.7`

设置那个变量后,mvn 运行良好。


1
原帖作者在使用苹果AppLauncher时遇到了问题,该应用程序包含Oracle Java。这与通过命令行上的java命令行存根启动maven的操作无关。 - Uwe Günther
1
@UweGünther,您当然是正确的。但对于只阅读OP问题(即未跟随其后的评论)的观众来说,就像我从Google搜索中找到这个问题时一样,合理的结论是这个问题是一个命令行问题,而不是您所发现和解决的更大问题。我想节省那些读者去徒劳地深入应用程序plist的兔子洞的时间,就像我做的那样。 - Andrew E

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接