如何在Mac OSX上安装Java并实现版本切换?

483

我想在Mac OSX上安装OpenJDK Java,并使其与其他JDK一起工作,因为它是一个更新的版本。目前,我已下载tar.gz并将其放置在路径中,但这很难维护。

我找到的另一个可以自动执行更多操作的安装方式是通过Homebrew cask进行安装。看起来只支持当前版本:

brew cask info java

展示:

Java: 13.33:5b8a42f3905b406298b72d750b6919f6
https://openjdk.java.net/

那么我可以从那里安装它,但然后呢?我只能使用新版本吗?


仅仅是问一下,我们能否将问题标签限制在单个版本上?因为无论如何都没有特定版本的安装脚本/步骤。这是一个通用(非特定版本)的问题,只需要标记为[tag:Java-11]即可,因为我认为那是人们开始寻找问题和答案建议的地方。 - Naman
答案中的脚本包括特定版本,即使很容易将它们解释为其他版本。但是,这也是社区成员寻找的一部分,因此通过帮助注意更新和现代化的答案,并区分于旧的过时的版本6和版本8主题,有助于帮助他们快速找到正确的答案。我认为保持最新稳定版本和最新新版本是合理的标签。 - Jayson Minard
我建议使用 jenv 来管理多个 Java 版本。 - panza
11个回答

1157
注意:这些解决方案适用于包括Java 8到Java 21(LTS版本)在内的各个版本的Java。这包括来自OpenJDK、Oracle、IBM、Azul、Amazon Correto、Graal等的替代JDK。
您有几种选择来进行安装和管理JDK的切换。可以通过Homebrew、SDKMANasdf或手动安装来进行安装。可以通过SDKMANasdf或手动设置JAVA_HOME来进行切换。以下将对所有这些进行描述。

TL;DR - 首选安装方法

您可以使用您喜欢的任何方法来安装Java,包括SDKMAN、asdf、Homebrew,或者手动安装tar.gz文件。手动安装的优点是可以将JDK的位置放在Mac OSX的标准位置。

然而,还有更简单的选择,比如SDKMANasdf,它们还会安装JVM的其他重要和常用工具。这两个主要选项在这里进行了描述。

使用SDKMAN安装和切换版本

SDKMAN有点不同,它处理安装和切换两个过程。SDKMAN还将安装的JDK放在自己的目录树中,通常是~/.sdkman/candidates/java。SDKMAN允许设置全局默认版本和当前shell特定的版本。

  1. https://sdkman.io/install安装SDKMAN

  2. 列出可用的Java版本,确保您知道版本ID

    sdk list java
    
  3. 安装其中一个版本,例如Java 21 LTS:

    sdk install java 21-open 
    

    或者Java 19:

    sdk install java 19.0.2-open
    
  4. 将Java 17设置为默认版本:

    sdk default java 17-open
    

    或者在当前终端会话中切换到17:

    sdk use java 17-open
    
当您使用列表命令列出可安装的版本时,您将看到各种各样的Java发行版。
sdk list java

安装其他版本,例如来自亚马逊的JDK 11。
sdk install java 11.0.14.10.1-amzn

SDKMAN可以与先前安装的现有版本一起使用。只需进行本地安装,提供您自己的版本标签和JDK的位置即可:
sdk install java my-local-13 /Library/Java/JavaVirtualMachines/jdk-13.jdk/Contents/Home

随意使用它:
sdk use java my-local-13

SDKMAN会在您更改版本时自动管理您的PATH和JAVA_HOME。另外,请注意,它会将Java版本安装到~/.sdkman/candidates/java/目录下。
更多信息可在SDKMAN使用指南中找到,其中还包括它可以安装和管理的其他SDK,如Gradle、Maven、Kotlin、Quarkus、Spring Boot等等。

使用 "asdf" 安装和切换版本

asdf 是一个版本管理工具,支持安装和管理大多数编程语言、框架和开发/运维工具。它还具有针对特定语言的插件,包括一个 Java 的插件

首先,通过https://asdf-vm.com/guide/getting-started.html安装asdf(请在那里阅读并正确设置您的shell),或者更简单地执行以下命令:
brew reinstall asdf
如果您使用Homebrew和ZSH来使用asdf,您可以执行以下命令完成设置,并阅读文档以正确设置您的shell:
echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ${ZDOTDIR:-~}/.zshrc

然后,通过https://github.com/halcyon/asdf-java安装Java插件:
asdf plugin add java
并在继续之前阅读文档以正确设置您的shell。基本上,它要求您将以下内容添加到您的~/.zshrc文件(假设您没有使用其他shell):
. ~/.asdf/plugins/java/set-java-home.zsh

现在列出Java版本:
asdf list-all java

安装您喜欢的版本:
asdf install java openjdk-21
或者安装最新版本:
asdf install java latest

其他重要的命令包括...
列出已安装的版本: asdf list java
设置全局Java版本: asdf global java openjdk-21
为目录设置本地Java版本: asdf local java openjdk-19
这就是这么简单!当你切换版本时,asdf会自动为你管理PATH和JAVA_HOME。值得一提的是,asdf会将Java版本安装到~/.asdf/installs/java目录下。
在仓库页面上,还有其他语言和插件可供asdf使用:https://github.com/asdf-vm/asdf-plugins

其他安装方法

使用Homebrew安装

在2018年10月3日之前,Homebrew Cask中提供的Java版本确实是Oracle JVM。然而,现在已经更新为OpenJDK。请确保更新Homebrew,然后您将看到可供安装的最新版本。

  1. 如果你还没有安装Homebrew,请先安装Homebrew。确保它已经更新:

     brew update
    
  2. 添加casks tap:

     brew tap homebrew/cask-versions
    

    这些casks经常更改它们的Java版本,可能还有其他tap包含额外的Java版本。

  3. 查找可安装的版本:

     brew search java  
    

    或者查找Eclipse Temurin版本:

     brew search temurin     
    
  4. 查看将要安装的版本的详细信息:

     brew info java
    

    或者查看Temurin版本的详细信息:

     brew info temurin
    
  5. 安装特定版本的JDK,例如java11temurin8temurin11temurin17,或者只是javatemurin以获取最新的发行版。例如:

     brew install java
    
     brew install --cask temurin
    
这些将被安装到Mac OSX上预期的传统位置/Library/Java/JavaVirtualMachines/。安装过程结束时可能会报告使JDK生效的额外步骤。

从OpenJDK下载页面手动安装:

如果您需要任何版本的Java,这是一个好地方。

  1. http://jdk.java.net/(例如Java 17Java 21)下载Mac OSX的OpenJDK。

  2. 解压OpenJDK tar文件,并将结果文件夹(即jdk-19.jdk)放入/Library/Java/JavaVirtualMachines/文件夹中,因为这是JDK安装的标准和预期位置。实际上,您也可以安装在任何您想要的地方。

  3. JAVA_HOME环境变量设置为指向您解压JDK的目录。

如需更多信息,请参阅答案关于手动安装的具体内容。此外,还可以查看下面的“手动切换版本”部分,了解如何管理多个手动安装的更多信息。

其他安装选项:

一些其他的OpenJDK版本包括:

Azul Systems Java Zulu 是OpenJDK的经过认证的构建版本,可以按照他们网站上的说明进行安装

Zulu® 是OpenJDK的经过认证的构建版本,完全符合Java SE标准。Zulu是100%开源且可免费下载的。现在,Java开发人员、系统管理员和最终用户可以享受开源Java的全部好处,并具备部署灵活性和对升级时间的控制。

Amazon Correto OpenJDK构建具有易于使用的Java 8、11、17和Java 21安装包。它安装到Mac OSX上的标准/Library/Java/JavaVirtualMachines/目录。

Amazon Corretto是一个免费的、跨平台的、生产就绪的Open Java Development Kit(OpenJDK)发行版。Corretto具有长期支持,包括性能增强和安全修复。亚马逊在数千个生产服务中内部运行Corretto,并且Corretto已通过Java SE标准的兼容性认证。使用Corretto,您可以在流行的操作系统上开发和运行Java应用程序,包括Linux、Windows和macOS。

Microsoft Java JDK - 来自Microsoft的经过认证的OpenJDK构建。


我的JDK在哪里?!?!

要查找先前安装在默认系统位置的Java JDK的位置,请使用:

/usr/libexec/java_home -V

匹配的Java虚拟机(4): 19(x86_64)"Homebrew" - "OpenJDK 19" /usr/local/Cellar/openjdk/19/libexec/openjdk.jdk/Contents/Home 18.0.1.1(x86_64)"Homebrew" - "OpenJDK 18.0.1.1" /usr/local/Cellar/openjdk/18.0.1.1/libexec/openjdk.jdk/Contents/Home 17(x86_64)"Homebrew" - "OpenJDK 17" /usr/local/Cellar/openjdk/17/libexec/openjdk.jdk/Contents/Home 11,x86_64:"Java SE 11" /Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home 1.8.301.09(x86_64)"Oracle Corporation" - "Java" /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home /usr/local/Cellar/openjdk/17/libexec/openjdk.jdk/Contents/Home 您还可以使用-v报告特定Java版本的位置。例如,对于Java 17:
/usr/libexec/java_home -v 17

/usr/local/Cellar/openjdk/17/libexec/openjdk.jdk/Contents/Home

知道已安装的JDK的位置对于使用工具如JEnv或手动将本地安装添加到SDKMAN也很有用 - 您需要知道它们的位置。
如果您需要查找其他工具安装的JDK,请检查以下位置:
- SDKMAN安装到~/.sdkman/candidates/java/ - asdf安装到~/.asdf/installs/java

版本切换

如果您正在使用SDKMANasdf,那么您已经完成了,可以停止阅读!否则,以下是一些切换现有虚拟机安装的选项。

手动切换版本

Java可执行文件是一个包装器,它将使用配置在JAVA_HOME中的任何JDK,因此您可以更改它来改变正在使用的JDK。

例如,如果您将JDK 16安装或解压缩到/Library/Java/JavaVirtualMachines/jdk-16.jdk,如果它是最高版本号,则应该已经是默认版本,否则您可以简单地设置:

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-16.jdk/Contents/Home

现在,无论在路径中有什么Java可执行文件,都会看到这个并使用正确的JDK。
更改JDK的一个简单方法是在您的~/.bashrc~/.zshrc文件中创建一个函数。
jdk() {
    version=$1
    export JAVA_HOME=$(/usr/libexec/java_home -v"$version");
    java -version
}

然后只需通过以下方式更改JDK:
jdk 1.8
jdk 9
jdk 11
jdk 13

编辑:
- 删除了Jabba和JENV,因为它们似乎已经停滞不前,问题数量急剧上升,并且问题/PR没有得到维护者的解决。

3
对于手动安装,我认为您需要设置JAVA_HOME以选择特定的版本,类似于在您的.bash_profile中使用export JAVA_HOME=$(/usr/libexec/java_home -v <version>) - Peter Hull
2
Java在brew cask中于2018年10月3日昨天更改为OpenJDK 11。 - Alpha Huang
41
可能是在MacOS上运行不同JDK版本的最全面、最有用的答案,涵盖了许多不同的方法,其中一些我以前从未听说过。 - Kevin Hooke
2
对于那些考虑使用 sdkman 安装 JDK 并使用 jenv 在它们之间切换的人:你需要知道 sdkman 安装的 JAVA_HOME 等效路径是 ~/.sdkman/candidates/java/<identifier>。但是,如果你可以使用 brew 而不是 sdkman,那会更容易一些。 - hmijail
1
是否可以在Mac上为某些程序设置特定的Java版本,就像这个讨论中所说的那样?https://community.ui.com/questions/Running-Unifi-Controller-on-Java-9-10-and-11/f1ac1330-40b8-4af6-83b6-8d55e48e4a32 - bomben
显示剩余20条评论

38

这是我是如何做到的。

步骤1:安装Java 11

您可以从这里下载Mac的Java 11 dmg:https://www.oracle.com/technetwork/java/javase/downloads/jdk11-downloads-5066655.html

步骤2:在安装Java 11后,请确认所有版本的安装情况。在终端中键入以下命令。

/usr/libexec/java_home -V

步骤 3:编辑 .bash_profile 文件

sudo nano ~/.bash_profile

第四步:将11.0.1添加为默认版本。(在bash_profile文件中添加以下行)。

export JAVA_HOME=$(/usr/libexec/java_home -v 11.0.1)

切换到任何版本

export JAVA_HOME=$(/usr/libexec/java_home -v X.X.X)

现在按下CTRL+X以退出bash。按下'Y'以保存更改。

步骤5:重新加载bash_profile

source ~/.bash_profile

第 6 步:确认当前 Java 的版本

java -version

不错的解决方案。但是如果我已经导出了JAVA_HOME 11,而java -version仍然指向8怎么办? - AlexGera
4
这个问题是关于Open JDK的,但你提供了Oracle JDK的链接。Open JDK似乎没有安装程序或安装说明。 - Splaktar
1
回复 @AlexGera - 添加以下行: export $PATH=$JAVA_HOME/bin:$PATH - Fuad Efendi
在添加@FuadEfendi的代码行后,我仍然需要执行此命令。 % export JAVA_HOME=/usr/libexec/java_home -v 17.0.1。确保在版本号末尾添加 ' 符号,因为它是代码格式化程序所需的。 - ever alian

16

使用Homebrew和jenv:

假设您正在Mac机器上,并且已经安装了homebrew。

从官方的Oracle网站安装Java。您可以安装多个JDK版本。它将安装在以下路径下:

 /Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/
 /Library/Java/JavaVirtualMachines/jdk1.11.0_2.jdk/
 /Library/Java/JavaVirtualMachines/jdk-14.0.2.jdk/

没有jenv,系统会使用最后安装的Java版本。

如果您想使用/管理多个Java版本,则可以使用jenv

安装和配置jenv:

$ brew install jenv
$ echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.zshrc
$ echo 'eval "$(jenv init -)"' >> ~/.zshrc
$ source ~/.zshrc
将已安装的Java添加到jenv中:
$ jenv add /Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/14.0.2.jdk/Contents/Home

查看所有已安装的Java:

$ jenv versions

以上命令将给出已安装的Java列表:

  system
  1.8
* 1.8.0.291 (set by /Users/lpatel/.jenv/version)
  14
  14.0
  14.0.2
  oracle64-1.8.0.291
  oracle64-14.0.2

配置您想要使用的Java版本:

$ jenv global 1.8.0.291

1
Error: caskroom/cask was moved. Tap homebrew/cask-cask instead, then fatal: repository 'https://github.com/Homebrew/homebrew-cask-cask/' not found - ChumiestBucket
@ChumiestBucket所说的-这个解决方案有多个问题。 - WestCoastProjects
3
@ChumiestBucket 我已经更新了解决方案,请让我知道您在此方案中是否遇到任何问题。谢谢! - Lyncean Patel
@WestCostProjects FYI - Lyncean Patel

13

手动切换系统默认版本而不使用第三方工具:

此旧回答所述,macOS上的/usr/bin/java是一个包装工具,它将使用JAVA_HOME指向的Java版本,如果该变量未设置,则会查找/Library/Java/JavaVirtualMachines/下的Java安装,并使用版本最高的那个。它通过查看每个包中的Contents/Info.plist来确定版本。

有了这个知识,您可以:

  • 通过重命名您不想用作默认的版本中的Info.plist文件(该文件实际上不被Java运行时本身使用)来控制系统将使用哪个版本。
  • 通过设置$JAVA_HOME来控制特定任务要使用的版本。

我刚刚验证了在OpenJDK和Mojave上仍然有效。

在全新的系统上,没有安装任何Java版本:

$ java -version
No Java runtime present, requesting install.

取消此操作,请在https://jdk.java.net下载OpenJDK 11和12ea; 安装OpenJDK11:

$ cd /Library/Java/JavaVirtualMachines/
$ sudo tar xzf ~/Downloads/openjdk-11.0.1_osx-x64_bin.tar.gz

Java 系统现在为 11 版本。

$ java -version
openjdk version "11.0.1" 2018-10-16
[...]

安装OpenJDK12(目前是早期版本):

$ sudo tar xzf ~/Downloads/openjdk-12-ea+17_osx-x64_bin.tar.gz 

Java系统现在为12版:

$ java -version
openjdk version "12-ea" 2019-03-19
[...]

现在让我们将OpenJDK 12“隐藏”起来,以避免影响系统的Java包装程序:

$ cd jdk-12.jdk/Contents/
$ sudo mv Info.plist Info.plist.disabled

Java 系统回到了 11 版本:

$ java -version
openjdk version "11.0.1" 2018-10-16
[...]

你仍然可以通过手动设置 JAVA_HOME 来准时使用版本12:

$ export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-12.jdk/Contents/Home
$ java -version
openjdk version "12-ea" 2019-03-19
[...]

1
现在采用AdoptOpenJDK构建,这也是正确的。 - Hugues M.

10
如果您在电脑上安装了多个版本,请在bash配置文件中添加以下内容:

export JAVA_HOME_7=$(/usr/libexec/java_home -v1.7)

export JAVA_HOME_8=$(/usr/libexec/java_home -v1.8)

export JAVA_HOME_9=$(/usr/libexec/java_home -v9)

并添加以下别名:

alias java7='export JAVA_HOME=$JAVA_HOME_7'

alias java8='export JAVA_HOME=$JAVA_HOME_8'

alias java9='export JAVA_HOME=$JAVA_HOME_9'

通过使用别名可以切换到所需的版本:
在终端中:

~ >> java7 export JAVA_HOME=$JAVA_7_HOME


1
是的,这个问题在另一个答案中已经涉及到了。 - Jayson Minard

4

另一种选择是使用SDKMAN!请查看https://wimdeblauwe.wordpress.com/2018/09/26/switching-between-jdk-8-and-11-using-sdkman/

首先安装SDKMAN:https://sdkman.io/install,然后...

  1. 使用以下命令安装Oracle JDK 8: sdk install java 8.0.181-oracle
  2. 使用以下命令安装OpenJDK 11: sdk install java 11.0.0-open

切换到所需的JDK版本:

  • 使用以下命令切换到JDK 8: sdk use java 8.0.181-oracle
  • 使用以下命令切换到JDK 11: sdk use java 11.0.0-open

设置默认JDK版本:

  • 使用以下命令将默认JDK版本设置为JDK 8: sdk default java 8.0.181-oracle
  • 使用以下命令将默认JDK版本设置为JDK 11: sdk default java 11.0.0-open

3

您可以使用asdf来安装和切换多个Java版本。它还有其他语言的插件。您可以使用Homebrew安装asdf。

brew install asdf

当配置asdf后,安装Java插件

asdf plugin-add java

选择要安装的版本

asdf list-all java

例如,安装和配置AdoptOpenJDK8。
asdf install java adoptopenjdk-8.0.272+10
asdf global java adoptopenjdk-8.0.272+10

如果需要,最后为您的 shell 配置 JAVA_HOME。 只需将其添加到您的 shell 初始化脚本中,例如在 zsh 的情况下是 ~/.zshrc:

. ~/.asdf/plugins/java/set-java-home.zsh

1
我认为没有必要安装所有的额外应用程序/软件包。
使用以下命令检查可用版本:
> /usr/libexec/java_home -V
Matching Java Virtual Machines (8):
    11, x86_64: "Java SE 11-ea" /Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home
    10.0.2, x86_64: "Java SE 10.0.2"    /Library/Java/JavaVirtualMachines/jdk-10.0.2.jdk/Contents/Home
    9.0.1, x86_64:  "Java SE 9.0.1" /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home
    1.8.0_181-zulu-8.31.0.1, x86_64:    "Zulu 8"    /Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home
    1.8.0_151, x86_64:  "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home
    1.7.0_80, x86_64:   "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home
    1.6.0_65-b14-468, x86_64:   "Java SE 6" /Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
    1.6.0_65-b14-468, i386: "Java SE 6" /Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

如果您想在上面的列表中选择 Azul JDK 8 而不是 Oracle 的 Java SE 8,请按以下命令调用:

> /usr/libexec/java_home -v 1.8.0_181
/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home

要选择Oracle的Java SE 8,您需要调用以下命令:
> /usr/libexec/java_home -v 1.8.0_151
/Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home

正如您所看到的,提供的版本号应该是唯一的字符串集合:1.8.0_181与1.8.0_151


第一个示例不应该有版本字符串 1.8.0_181-zulu-8.31.0.1 吗?还是只是部分匹配? - Jayson Minard
这实际上并不改变使用Java的版本,它只是报告JAVA_HOME的位置。手动切换使用这些命令在我的其他答案中有介绍。 - Jayson Minard

1
这篇答案在Jayson的优秀回答基础上进一步提供了一些关于最佳实践的有见地指导,适用于您的用例:
  • SDKMAN 是大多数用户的最佳解决方案。它易于使用,没有奇怪的配置,并且使管理许多其他 Java 生态系统项目的多个版本变得容易。
  • 通过 Homebrew 下载 Java 版本并通过 jenv 切换版本是一个不错的选择,但需要更多的工作。例如,在这个高票答案中的 Homebrew 命令 不再起作用。jenv 需要稍微更难的设置,插件文档不够完整,README 说该项目正在寻找新的维护者。jenv 仍然是一个伟大的项目,可以解决工作问题,社区应该感谢这个精彩的贡献。 SDKMAN 只是更好的选择,因为它太棒了。
  • Jabba 是一个跨平台解决方案,可在 Mac、Windows 和 PC 上提供相同的接口(它是用 Go 编写的,这就允许它是跨平台的)。如果您关心跨平台解决方案,则这是一个巨大的卖点。如果您只关心在 Mac 上运行多个版本,则不需要跨平台解决方案。 如果您选择 Jabba,则会错过 SDKMAN 对数十个流行 SDK 的支持。
手动管理版本可能是最糟糕的选择。如果您决定手动切换版本,可以使用此Bash代码代替Jayson的冗长代码(代码片段来自homebrew-openjdk README
jdk() {
        version=$1
        export JAVA_HOME=$(/usr/libexec/java_home -v"$version");
        java -version
 }

Jayson的回答提供了SDKMAN和jenv的基本命令。如果您想了解这些工具的更多背景信息,请参考SDKMANjenv的更多信息。


谢谢,我已经更新了原始答案,以便更简单地切换 shell。 - Jayson Minard

0

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