122

(不确定这是否应该继续 SU...迁移当然是一种选择,但更多的程序员在这里阅读问题,所以这里是)。

我正在运行 Mac OS X 10.8.4,并且安装了 Apple 的 JDK 1.6.0_51 以及 Oracle 的 JDK 1.7.0_25。我最近为一些需要它的预发布软件安装了 Oracle 的 1.8 预览版 JDK。现在,当我运行 /usr/libexec/java_home 时,我得到了这个:

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (4):
    1.8.0, x86_64:  "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home
    1.7.0_25, x86_64:   "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home
    1.6.0_51-b11-457, x86_64:   "Java SE 6" /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
    1.6.0_51-b11-457, i386: "Java SE 6" /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

伟大的。

但是,运行:

$ java -version

回报:

java version "1.8.0-ea"

这意味着 Java 的默认版本当前是预发布版本,它破坏了一些“正常”包(在我的例子中是 VisualVM)。

我无法设置JAVA_HOME,因为启动应用程序会忽略环境变量,即使是从命令行启动时(例如$ open /Applications/VisualVM.app)。

那么,有没有我可以编辑的文件,我可以在其中全局设置我的 JVM 排序首选项?

(请不要告诉我启动 Java 首选项面板,因为这根本不起作用:它不包含任何有用的东西,只列出了我安装的 4 个 JVM 之一。)

更新

Oracle JVM 存在于/Library/Java/JavaVirtualMachines. 将 JDK 1.8 目录重命名为jdk1.8.0.jvm.xyz不会改变任何内容:java_home仍然在正确的位置找到它,并且运行 /usr/bin/java 仍然执行 1.8 JVM。这不是synlinks等的问题。

类似问题的答案

虽然这个答案提供了相当于删除 Java 版本被 java_home 获取的黑客攻击,但它仍然没有回答java_home如何选择其默认值以及用户是否可以非破坏性设置它的问题

4

12 回答 12

91

我认为这JAVA_HOME是你能做的最好的。命令行工具喜欢java并将javac尊重该环境变量,您可以使用/usr/libexec/java_home -v '1.7*'它为您提供合适的值以JAVA_HOME使命令行工具使用 Java 7。

export JAVA_HOME="`/usr/libexec/java_home -v '1.7*'`"

但是标准的可双击应用程序包根本不使用安装在其下/Library/Java的 JDK。使用 Apple 的旧式.app捆绑包JavaApplicationStub将使用来自 的 Apple Java 6 /System/Library/Frameworks,而使用AppBundler构建但没有捆绑 JRE 的新式捆绑包将使用“公共”JRE /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home- 这是在存根代码中硬编码且无法更改的,并且您不能同时安装两个不同的公共 JRE。


编辑:我专门查看了 VisualVM,假设您使用的是下载页面中的“应用程序包”版本,并且这个特定的应用程序不是 AppBundler 应用程序,而是它的主要可执行文件是一个调用数字的 shell 脚本其他 shell 脚本并读取各种配置文件。它默认选择最新的 JDK,/Library/Java只要它是 7u10 或更高版本,或者如果您的 Java 7 安装是更新 9 或更早版本,则使用 Java 6。但是解开 shell 脚本中的逻辑,在我看来,您可以使用配置文件指定特定的 JDK。

创建一个~/Library/Application Support/VisualVM/1.3.6/etc/visualvm.conf包含该行的文本文件(将 1.3.6 替换为您正在使用的任何版本的 VisualVM)

visualvm_jdkhome="`/usr/libexec/java_home -v '1.7*'`"

这将迫使它选择 Java 7 而不是 8。

于 2013-07-26T16:20:54.747 回答
56

我也去过那里,到处搜索它是如何/usr/libexec/java_home工作的,但我找不到任何关于它如何确定它列出的可用 Java 虚拟机的信息。

我做了一些实验,我认为它只是执行 als /Library/Java/JavaVirtualMachines然后检查./<version>/Contents/Info.plist它在那里找到的所有运行时。

然后它按 Info.plist 中包含的键对它们进行降序排序JVMVersion,默认情况下它使用第一个条目作为其默认 JVM。

我认为我们唯一可能做的就是更改 plist:sudo vi /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Info.plist然后将 JVMVersion 修改1.8.0为其他内容,使其排序到底部而不是顶部,例如!1.8.0.

就像是:

<?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>
    ...
    <dict>
            ...
            <key>JVMVersion</key>
            <string>!1.8.0</string>   <!-- changed from '1.8.0' to '!1.8.0' -->`

然后它神奇地从列表顶部消失:

/usr/libexec/java_home -verbose
Matching Java Virtual Machines (3):
    1.7.0_45, x86_64:   "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home
    1.7.0_09, x86_64:   "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_09.jdk/Contents/Home
    !1.8.0, x86_64: "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home

现在您需要注销/登录,然后:

java -version
java version "1.7.0_45"

:-)

当然,我不知道现在是否有其他问题,或者 java 的 1.8.0-ea 版本是否仍然可以正常工作。

您可能不应该这样做,而只需卸载 1.8.0。

但是到目前为止,这对我有用。

于 2014-01-08T11:54:49.737 回答
10

这实际上很容易。假设我们的 JavaVirtualMachines 文件夹中有这个:

  • jdk1.7.0_51.jdk
  • jdk1.8.0.jdk

假设 1.8 是我们的默认值,那么我们只需添加一个新文件夹(例如“旧”)并将默认 jdk 文件夹移动到该新文件夹。再做java -version一次,瞧,1.7!

于 2014-02-08T09:09:07.093 回答
7

实际上,我在反汇编程序中看了一点,因为源不可用。

/usr/bin/java 和 /usr/libexec/java_home 都使用 JavaLaunching.framework。JAVA_HOME 环境变量确实首先由 /usr/bin/java 和朋友(但不是 /usr/libexec/java_home)检查。框架使用 JAVA_VERSION 和 JAVA_ARCH 环境变量来过滤可用的 JVM。所以,默认情况下:

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (2):
    11.0.5, x86_64: "Amazon Corretto 11"    /Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home
    1.8.0_232, x86_64:  "Amazon Corretto 8" /Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home

但是设置,比如说, JAVA_VERSION 可以覆盖默认值:

$ JAVA_VERSION=1.8 /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home

您还可以设置 JAVA_LAUNCHER_VERBOSE=1 以查看一些额外的调试日志,例如搜索路径、找到的 JVM 等,包括 /usr/bin/java 和 /usr/libexec/java_home。

过去,JavaLaunching.framework 实际上使用首选项系统(在 com.apple.java.JavaPreferences 域下)设置首选 JVM 顺序,允许使用 PlistBuddy 设置默认 JVM - 但据我所知,最新版本的 macOS 中已删除代码。环境变量似乎是唯一的方法(除了在 JDK 包本身中编辑 Info.plist。)

设置默认环境变量当然可以通过您的 .profile 或launchd来完成,如果您需要在会话级别设置它们。

于 2019-10-31T23:40:21.020 回答
5

这很简单,如果您不介意卷起袖子... /Library/Java/Home是 JAVA_HOME 的默认值,它只是指向以下之一的链接:

  • /System/Library/Java/JavaVirtualMachines/1.?.?.jdk/Contents/Home
  • /Library/Java/JavaVirtualMachines/jdk1.?.?_??.jdk/Contents/Home

所以我想更改我的默认 JVM/JDK 版本而不更改 JAVA_HOME 的内容... /Library/Java/Home 是当前 JVM/JDK 的标准位置,这就是我想要保留的...在我看来以最简单的方式以最少的副作用改变事物。

其实很简单。为了更改您使用 java -version 看到的 java 版本,您所要做的就是某个版本:

cd /Library/Java
sudo rm Home
sudo ln -s /Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home ./Home

我没有花时间,但是一个非常简单的 shell 脚本使用 /usr/libexec/java_home 和 ln 来重新指向上面的符号链接应该很容易创建......

一旦你改变了 /Library/Java/Home 指向的位置......你会得到正确的结果:

cerebro:~ magneto$ java -version
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27) Java HotSpot(TM)
64-Bit Server VM (build 25.60-b23, mixed mode)
于 2015-09-08T20:33:47.410 回答
4

我测试了“jenv”和其他设置“JAVA_HOME”但没有成功。现在我得到了以下解决方案:

function setJava {
    export JAVA_HOME="$(/usr/libexec/java_home -v $1)"
    launchctl setenv JAVA_HOME $JAVA_HOME
    sudo ln -nsf "$(dirname ${JAVA_HOME})/MacOS" /Library/Java/MacOS 
    java -version
}

(添加到 ~/.bashrc 或 ~/.bash.profile 或 ~/.zshrc)

像这样打电话:

setJava 1.8

java_home 将处理错误的输入。所以你不能做错事。Maven 和其他东西现在会选择正确的版本。

于 2019-04-19T14:34:46.480 回答
3

Oracle 的Java 7 卸载说明对我有用。

摘抄:

卸载 JDK 要卸载 JDK,您必须具有管理员权限并以 root 身份或使用 sudo(8) 工具执行删除命令。

导航到 /Library/Java/JavaVirtualMachines 并删除名称与以下格式匹配的目录:*

/Library/Java/JavaVirtualMachines/jdk<major>.<minor>.<macro[_update]>.jdk

例如,要卸载 7u6:

% rm -rf jdk1.7.0_06.jdk

于 2013-11-07T03:31:07.573 回答
3

有点晚了,但因为这是 Mac OSX 的一个持续问题......

我找到的最简单的解决方案是简单地删除 Apple 安装的 OpenJDK 内容。每次 Mac OSX 的更新到达时,它都会被安装,您需要再次将其删除。

如果您在 Mac 上使用 Java 为 Google App Engine 开发应用程序,这将非常有效。OpenJDK 无法正常运行,Mac OSX Yosemite 升级附带的 Java 版本会导致 Eclipse Plug-in for App Engine 在每次部署时崩溃,并出现有用的错误:“读取超时”。

于 2014-11-12T19:46:15.447 回答
-1

编辑:此信息专门针对 visualvm,不适用于任何其他 java 应用程序

正如其他人所说,您需要修改visualvm.conf

对于 Mac 上最新版本的 JvisualVM 1.3.6,安装目录已更改。

它当前位于 /Applications/VisualVM.app/Contents/Resources/visualvm/etc/visualvm.conf中。

但是,这可能取决于您安装 VisualVM 的位置。找到 VisualVM 的最简单方法是在哪里启动它,然后使用以下命令查看该过程:

ps -ef | grep 视觉虚拟机

你会看到类似的东西:

... -Dnetbeans.dirs=/Applications/VisualVM.app/Contents/Resources/visualvm/visualvm ...

您想要获取 netbeans.dir 属性并查找目录,您将找到 etc 文件夹。

在 visualvm.conf 中取消注释此行并更改 jdk 的路径

visualvm_jdkhome="/path/to/jdk"

此外,如果您的 visualvm 运行缓慢并且内存很大,我建议大大增加可用内存量并在服务器模式下运行它:

visualvm_default_options="-J-XX:MaxPermSize=96m -J-Xmx2048m -J-Xms2048m -J-server -J-XX:+UseCompressedOops -J-XX:+UseConcMarkSweepGC -J-XX:+UseParNewGC -J-XX:NewRatio=2 -J-Dnetbeans.accept_license_class=com.sun.tools.visualvm.modules.startup.AcceptLicense -J-Dsun.jvmstat.perdata.syncWaitMs=10000 -J-Dsun.java2d.noddraw=true -J-Dsun.java2d.d3d=false"
于 2013-11-19T19:43:46.390 回答
-2

我有类似的情况,以下过程对我有用:

  1. 在终端中,键入

    vi ~/.profile
    
  2. 然后在文件中添加这一行,并保存

    export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk<version>.jdk/Contents/Home
    

    其中 version 是您计算机上的版本,例如 1.7.0_25

  3. 退出编辑器,然后键入以下命令使其生效

    source ~/.profile 
    

然后输入 java -version 查看结果

    java -version 

什么是.profile?来自:http ://computers.tutsplus.com/tutorials/speed-up-your-terminal-workflow-with-command-aliases-and-profile--mac-30515

.profile 文件是一个隐藏文件。它是一个可选文件,它告诉系统在其配置文件登录的用户登录时运行哪些命令。例如,如果我的用户名是 bruno,并且 /Users/bruno/ 中有一个 .profile 文件,则它的所有内容将在登录过程中执行。

于 2014-02-11T06:52:12.060 回答
-2

MacOS 使用 /usr/libexec/java_home 来查找当前的 Java 版本。绕过的一种方法是更改​​ plist 文件,如上面@void256 所述。其他方法是备份 java_home 并用您自己的脚本 java_home 替换它,代码
echo $JAVA_HOME

现在,通过将以下命令添加到 ~/.bash_profile,将 JAVA_HOME 导出到所需的 SDK 版本。export JAVA_HOME="/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home" launchctl setenv JAVA_HOME $JAVA_HOME /// 将环境变量设为全局

运行命令 source ~/.bash_profile 来运行上述命令。

任何时候需要更改 JAVA_HOME,他都可以在 ~/.bash_profile 文件中重置 JAVA_HOME 值。

于 2014-07-29T11:35:18.870 回答
-3

我想将默认的 Java 版本从 1.6* 更改为 1.7*。我尝试了以下步骤,它对我有用:

  • 从 /usr/bin 下删除了链接“java”
  • 再次创建它,指向新位置:

ln -s /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/bin/java java

  • 用“java -version”验证

Java 版本“1.7.0_51”
Java(TM) SE 运行时环境(构建 1.7.0_51-b13)
Java HotSpot(TM) 64 位服务器 VM(构建 24.51-b03,混合模式)

于 2014-02-12T04:39:57.347 回答