如何更改从/ usr / libexec / java_home返回的Mac OS的默认Java VM


108

(不确定是否应该继续进行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 Preferences Panel,因为那根本行不通:它不包含任何有用的东西,仅列出了我已安装的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_home删除Java版本的黑客手段,但仍无法回答java_home 如何选择其默认值以及用户是否可以非破坏性地设置它的问题


键入“ which java”并遵循面包屑。/usr/bin/java只是一个符号链接
Brian Roach 2013年

11
去过也做过。/usr/bin/java指向/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java。该Versions目录不包含指向1.8.0 JDK的符号链接。相反,它包含一个名为有益目录A,其Current指向。A,是不是“JAVA_HOME它有一个名为的子目录Commands里面确实有一个java。命令,但它是一个不透明的通用二进制这确实谁也不知道的什么,我怀疑它使用java_home等来决定使用哪种JVM。
克里斯托弗·舒尔茨

2
如果这是题外话,请迁移而不是关闭。FWIW,这与“程序员常用的软件工具”有关,因此关闭“离题”是不明显的。
Christopher Schultz

是的,这令人沮丧!我只想要一个JDK,或者想要2个就可以轻松在1.7和1.8之间切换。
布赖恩

1
我发现此问题解答对于以下问题很有用:stackoverflow.com/a/44169445/2987755
dkb

Answers:


89

我认为这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*'`"

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


编辑:我专门看过VisualVM,假设您使用的是下载页面中的“应用程序捆绑包”版本,并且此特定应用程序不是AppBundler应用程序,而是其主要可执行文件是调用数字的Shell脚本。其他shell脚本并读取各种配置文件。默认情况下/Library/Java,只要是7u10或更高版本,就默认选择最新的JDK;如果Java 7安装为Update 9或更早版本,则使用Java 6。但是在我看来,揭露shell脚本中的逻辑就像您可以使用配置文件指定特定的JDK一样。

创建一个包含以下内容的文本文件~/Library/Application Support/VisualVM/1.3.6/etc/visualvm.conf(用您使用的任何版本的VisualVM替换1.3.6)

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

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


在我的系统上似乎不是这种情况。在安装JDK 1.8之前启动VisualVM可以正常工作。在JDK1.8之后,VisualVM将显示初始屏幕,然后消失。将JDK1.8目录移出/ Library / Java可以恢复其运行能力。
Christopher Schultz

@ChristopherSchultz我在VisualVM捆绑软件中查看了一下,结果发现它不是普通的appbundler应用程序。有关可能的解决方法,请参见我的编辑。
伊恩·罗伯茨

抱歉,我在编辑之前写了我以前的评论。我将检验使VisualVM使用该技术运行,但是它不太可能普遍适用。我还有很多其他基于Java的软件,例如Eclipse,JasperReports iReport等,它们都可能受此影响。我想我只想将JDK1.8目录移到其他位置,并在我实际需要的(几次)时间内将它与JAVA_HOME明确地结合使用。
Christopher Schultz

1
是的,您是对的,JAVA_HOME通常,最好的选择是在其他情况下指定所需的次要版本。基于拆卸,事实证明,你可以export JAVA_VERSION=1.7java_home默认显示JKD7而不是JDK8,但休息java_home -v 1.6,因为java-home将它解释为附加限制条件,并给出了由于相互不可满足的约束,那么就用默认的1.8甚至与云--failfast选项。
andrewdotn

2
我不明白为什么“系统偏好设置Java控制面板”不仅仅显示可供选择的列表,而不必求助于Shell脚本/命令。我怀疑这仅适用于在浏览器中运行的小程序...
JGFMK 2014年

51

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

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

然后,将它们JVMVersion Info.plist中包含的键降序排列,并且默认情况下,它将第一个条目用作其默认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。

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


这对我有用。我必须使用此调整才能使Idea Sbt插件在MacOS上为我工作。我在我的博客agilebuild.blogspot.com/2014/02/…中
antoine

此方法有效,但似乎有些棘手,可能看起来不像标准操作过程。如果有更好的方法,我会徘徊。
李微博

我仍然想要一个解决方案,但是为了将Intellij设置为JDK使用,我将其添加到了zshenv中:export IDEA_JDK = /usr/libexec/java_home -v 1.7。我想我也会为JAVA_HOME做同样的事情
David Resnick

我设法使用该答案来避免使用Java 9启动双击应用程序(由于Keystore Store资源管理器中的问题)。谢谢!
Nicolas Henneaux

2
在macOS上安装JDK和JRE的摘录:在为macOS 2012-006安装Java之后,/usr/bin/java将找到最新安装的JDK,并将其用于中的所有与Java相关的命令行工具/usr/bin
Jeremy Kao

7

实际上很简单。假设我们在JavaVirtualMachines文件夹中有此文件:

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

想象一下1.8是我们的默认文件夹,那么我们只需添加一个新文件夹(例如'old'),然后将默认的jdk文件夹移至该新文件夹。再做java -version一次,1.7!


1
令人难以置信,但它的工作...感谢的Mac OS莫哈韦
米哈尔DOBI多布然斯基

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

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

更改/ 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)

1
这不是这些东西的工作原理:/Library/Java/Home确实是一个符号链接,但它指出了/System/Library/Frameworks/JavaVM.framework/Home它本身处于大量的符号链接中,这些符号最终使您进入……一个神奇的命令,它确定了要启动的正确JRE。请注意,这/usr/libexec/java_home也链接到此魔术中。因此,您可以通过替换符号链接并指向单个JRE来中断所有操作,但是您每次都必须对其进行更新。显然没有set_preferred_jvm_version类似的命令。
Christopher Schultz

1
但是,此技术的优点是它不需要您在JAVA_HOME任何地方进行设置。我将研究这种技术,看看它是否会导致基于Java的程序使用“首选” Java VM启动。我怀疑会这样,但是它非常脆弱。
Christopher Schultz

好了,这些天我在.bash_profileexport JAVA_HOME=`/usr/libexec/java_home -v 12`
jrypkahauer

双击图标不起作用,这很重要。仅可从命令行使用的解决方案不是...。
Christopher Schultz

3

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

摘抄:

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

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

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

例如,要卸载7u6:

% rm -rf jdk1.7.0_06.jdk


2
这个问题不是关于卸载……而是关于从已安装的JVM中选择“主要” JVM……
Christopher Schultz

3

有点晚了,但是由于这是Mac OSX的持续问题...

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

如果您使用Java在Mac上为Google App Engine开发应用程序,则效果很好。OpenJDK不能很好地运行,并且Mac OSX Yosemite升级随附的Java版本会使每次部署的Eclipse Plug-in for App Engine崩溃,并出现有用的错误:“读取超时”。


1
有趣的是……我认为苹果此时已经完全删除了Java。我不记得手动删除Apple的Java 1.6 JVM,而且肯定不再在这里了。无论如何,这并不能真正解决最初的问题,即在已安装选择的情况下指定首选的JVM。
Christopher Schultz 2014年

你是对的。它没有回答问题。它确实回答了这个问题:如果删除正在使用的JVM,则使用列表中的“下一个”。也许有帮助。
Mo'in Creemers 2014年

这说明为什么在运行jdk 8安装后,它没有显示在JavaVirtualMachines文件夹中吗?无论安装什么版本,我看到的都是“ 1.6.0.jdk”。
whyoz

@whyoz刚刚在osx 10.10.2上安装了jdk-8u31-macosx-x64,并且该VM已按预期安装在JavaVirtualMachines文件夹中。
Mo'in Creemers 2015年

您是否偶然运行Parallels?我将其安装在Parallels的Windows侧,并按预期方式安装了8u31。只是不安装在Mac侧
。– whyoz

3

我测试了“ 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和其他东西现在将选择正确的版本。


1

我实际上在反汇编程序中对此做了一些研究,因为没有可用的源代码。

/ usr / bin / java和/ usr / libexec / java_home都使用JavaLaunching.framework。实际上,确实先由/ usr / bin / java和朋友(而不是/ usr / libexec / java_home)检查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来使用/ usr / bin / java和/ usr / libexec / java_home查看搜索路径,找到的JVM等其他调试日志。

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

当然,如果需要在会话级别设置默认环境变量,则可以通过.profile或通过launchd进行设置。


丹,这是很重要的信息。.profile对于我的用例(从例如启动板启动应用程序),使用不是很有用,但是技巧launchd很不错。我必须尝试一下,因为Java最近的版本控制疯狂意味着我同时安装了几代Java,并且具有(个人)信任级别。
Christopher Schultz,

-2

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

正如其他人所提到的,您需要修改visualvm.conf

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

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

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

ps -ef | grep VisualVM

您将看到类似以下内容:

... -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"

坏建议:修改特定应用程序的启动脚本可能会破坏该应用程序并且不能解决更改操作系统默认JVM的原始问题。
Christopher Schultz,

不幸的是,正如其他人所提到的,jvisualvm不使用标准方法来选择jvm。这是此应用程序的唯一解决方案。
Celandro

正如我在回答中指出的那样,您无需修改​​应用程序捆绑包本身内的任何内容,该应用程序可以从中加载其配置~/Library/Application Support/VisualVM/1.3.6/etc/visualvm.conf
伊恩·罗伯茨

-2

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

  1. 在终端中,键入

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

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

    版本是您计算机上的版本,例如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文件,则其所有内容将在登录过程中执行。


从启动板启动VisualVM时,这将不起作用。从命令行启动从来没有问题,因为您可以设置JAVA_HOME环境变量。
Christopher Schultz 2014年

-2

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

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

运行命令源〜/ .bash_profile来运行上述命令。

每当需要更改JAVA_HOME时,他都可以在〜/ .bash_profile文件中重置JAVA_HOME值。


任何依赖于环境变量的东西都将不起作用。关键是通过LaunchPad等启动的应用程序不会具有该环境设置。上面的plist hack看起来确实是“最好的”,因为它实际上达到了预期的结果。我不确定有什么缺点。看到@Tony的答案,它也有同样的问题。
Christopher Schultz

-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™SE运行时环境(内部版本1.7.0_51-b13)
Java HotSpot(TM)64位服务器VM(内部版本24.51-b03,混合模式)


没有回答这个问题:它不会影响的行为/usr/libexec/java_home
Christopher Schultz
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.