多数的 Java 入门教程都是要求同时设置 JAVA_HOME 和 PATH(包含 $JAVA_HOME/bin) 两个环境变量,反正两个都有了就保险。其实一般情况下系统能在 PATH 中找到 java 程序时就知道 JAVA_HOME, 基本上只要配置 PATH 就行,而 JAVA_HOME 环境变量是可选的。但也有例外,比如 TOMCAT 就可能要求有 JAVA_HOME 环境变量。
在 macOS 下,JAVA_HOME 与 PATH 的关系又显得有点微妙了。一个新的 macOS 系统,它自带有 java 命令
$ which java
/usr/bin/java
你要直接执行它的话
$ java
The operation couldn’t be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.
所以它实际上只是执行 java 的辅助入口,没有实际的 JDK 或 JRE 是没用的。
用 PATH 覆盖 /usr/bin/java
当我们把 JDK 安装在非默认目录,如 /Users/yanbin/amazon-corretto-11.jdk,我们可以配置 PATH 来使用这个 JDK
export PATH=/Users/yanbin/amazon-correto-11.jdk/Contents/Home/bin:$PATH
然后可以执行
$ java -version
openjdk version "11.0.14.1" 2022-02-08 LTS
注意自己的路径要放在 $PATH 之前,否则仍然会执行 /usr/bin/java, 从而找不到 Java
macOS 定位 JAVA_HOME 有一个自己的命令 /usr/libexec/java_home
, /usr/bin/java 就是仰赖于它来定位 JAVA_HOME 的。如果 JDK 在非默认目录中,/usr/libexec/java_home 是不知道的
$ /usr/libexec/java_home
The operation couldn’t be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.
虽然依据 PATH 是可以执行 java 程序的。
/usr/libexec/java_home 定位
前面提到 macOS 的 JDK 安装默认目录,那就是 /Library/Java/JavaVirtualMachines
, JDK 安装程序会安装 JDK 到该目录中,如
/Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk
这时候我们不需要配置 PATH 环境变量(把 PATH 环境变量恢复成默认,或打开一个新的终端),再执行 /usr/libexec/java_home 就能找到该默认位置下的 JDK11
$ /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home
执行 java
$ java -version
openjdk version "11.0.14.1" 2022-02-08 LTS
不光是执行 JDK 安装程序的方式,就是我们直接解压 JDK 到目录也行。例如我们解压 JDK 8 到该目录中
$ ls /Library/Java/JavaVirtualMachines
amazon-corretto-11.jdk amazon-corretto-8.jdk
看看此时 macOS 会选择哪个 JDK
1 2 3 4 5 6 7 8 9 10 11 |
$ /usr/libexec/java_home /Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home $ $ /usr/libexec/java_home -V Matching Java Virtual Machines (2): 11.0.14.1 (x86_64) "Amazon.com Inc." - "Amazon Corretto 11" /Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home 1.8.0_322 (x86_64) "Amazon" - "Amazon Corretto 8" /Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home /Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home $ $java -version openjdk version "11.0.14.1" 2022-02-08 LTS |
列出来两个 JDK, 但选择了 JDK 11
再来一个 JDk
$ ls /Library/Java/JavaVirtualMachines
amazon-corretto-11.jdk amazon-corretto-17.jdk amazon-corretto-8.jdk
1 2 3 4 5 6 7 8 9 |
$ /usr/libexec/java_home -V Matching Java Virtual Machines (3): 17.0.2 (x86_64) "Amazon.com Inc." - "Amazon Corretto 17" /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home 11.0.14.1 (x86_64) "Amazon.com Inc." - "Amazon Corretto 11" /Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home 1.8.0_322 (x86_64) "Amazon" - "Amazon Corretto 8" /Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home /Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home $ java -version openjdk version "17.0.2" 2022-01-18 LTS |
看来在 /Library/Java/JavaVirtualMachines 中有多个 JDK 版本时,/usr/libexec/java_home 会选择最高版本。
用 JAVA_HOME 选择 JDK 版本
那么如何让 /usr/bin/java 选择自己想要的 JDK 版本呢,设定 JAVA_HOME, 而不是让 /usr/libexec/java_home 自主选择最高的版本。
比如我们在 /Library/Java/JavaVirtualMachines 中有三个 JDK 版本时,想用 JDK 8
export JAVA_HOME=/Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home
$ java -version
openjdk version "1.8.0_322"
/usr/libexec/java_home 的高级用法
命令帮助
1 2 3 4 5 6 7 8 9 10 11 12 |
$ /usr/libexec/java_home --help Usage: java_home [options...] Returns the path to a Java home directory from the current user's settings. Options: [-v/--version <version>] Filter versions (as if JAVA_VERSION had been set in the environment). [-a/--arch <architecture>] Filter architecture (as if JAVA_ARCH had been set in the environment). [-F/--failfast] Fail when filters return no JVMs, do not continue with default. [ --exec <command> ...] Execute the $JAVA_HOME/bin/<command> with the remaining arguments. [-X/--xml] Print full JVM list and additional data as XML plist. [-V/--verbose] Print full JVM list with architectures. [-h/--help] This usage information. |
除了 /usr/libexec/java_home -V 可列出 /Library/Java/JavaVirtualMachines 中的所有 JDK 版本及路径,以及首选的 JDK 外,用 /usr/libexec/java_home -X 能以 plist XML 格式展示所有 JDK
$ /usr/libexec/java_home -X
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
<?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"> <array> <dict> <key>JVMArch</key> <string>x86_64</string> <key>JVMBundleID</key> <string>com.amazon.corretto.18</string> <key>JVMEnabled</key> <true/> <key>JVMHomePath</key> <string>/Library/Java/JavaVirtualMachines/amazon-corretto-18.jdk/Contents/Home</string> <key>JVMName</key> <string>Amazon Corretto 18</string> <key>JVMPlatformVersion</key> <string>18.0.0</string> <key>JVMVendor</key> <string>Amazon.com Inc.</string> <key>JVMVersion</key> <string>18.0.0</string> </dict> <dict> <key>JVMArch</key> <string>x86_64</string> <key>JVMBundleID</key> <string>com.amazon.corretto.17</string> <key>JVMEnabled</key> <true/> <key>JVMHomePath</key> <string>/Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home</string> <key>JVMName</key> <string>Amazon Corretto 17</string> <key>JVMPlatformVersion</key> <string>17.0.2</string> <key>JVMVendor</key> <string>Amazon.com Inc.</string> <key>JVMVersion</key> <string>17.0.2</string> </dict> <dict> <key>JVMArch</key> <string>x86_64</string> <key>JVMBundleID</key> <string>com.amazon.corretto.11</string> <key>JVMEnabled</key> <true/> <key>JVMHomePath</key> <string>/Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home</string> <key>JVMName</key> <string>Amazon Corretto 11</string> <key>JVMPlatformVersion</key> <string>11.0.14</string> <key>JVMVendor</key> <string>Amazon.com Inc.</string> <key>JVMVersion</key> <string>11.0.14.1</string> </dict> <dict> <key>JVMArch</key> <string>x86_64</string> <key>JVMBundleID</key> <string>com.amazon.corretto.8</string> <key>JVMEnabled</key> <true/> <key>JVMHomePath</key> <string>/Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home</string> <key>JVMName</key> <string>Amazon Corretto 8</string> <key>JVMPlatformVersion</key> <string>1.8</string> <key>JVMVendor</key> <string>Amazon</string> <key>JVMVersion</key> <string>1.8.0_322</string> </dict> </array> </plist> |
还能用 /usr/libexec/java_home -v xxx 智能的显示所对应版本的 JAVA_HOME
$ /usr/libexec/java_home -v 1.8
/Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home
$ /usr/libexec/java_home -v 11
/Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home
$ /usr/libexec/java_home -v 8
/Library/Java/JavaVirtualMachines/amazon-corretto-18.jdk/Contents/Home
结合 /usr/libexec/java_home -v xxx 选项,我们就可以用一个脚本来切换 JAVA_HOME,核心就是
export JAVA_HOME=$(/usr/libexec/java_home -v $1)
根据所使用 shell 的不同,比如我们可以在 ~/.bashrc 或 ~/.zshrc 文件中定义一个函数
1 2 3 4 5 6 7 8 9 10 |
switch_java() { JAVA_HOME=$(/usr/libexec/java_home -v $1) if [ -z $2 ]; then echo "switch JAVA_HOME to $JAVA_HOME" fi export JAVA_HOME } # set default JAVA_HOME switch_java 11 XX |
然后执行 switch_java 来切换
$ switch_java 11
$ switch_java 1.8
$ switch_java 17
Demo
$ java -version
openjdk version "11.0.14.1" 2022-02-08 LTS
OpenJDK Runtime Environment Corretto-11.0.14.10.1 (build 11.0.14.1+10-LTS)
OpenJDK 64-Bit Server VM Corretto-11.0.14.10.1 (build 11.0.14.1+10-LTS, mixed mode)
$ switch_java 1.8
switch JAVA_HOME to /Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home
$ java -version
openjdk version "1.8.0_322"
OpenJDK Runtime Environment Corretto-8.322.06.1 (build 1.8.0_322-b06)
OpenJDK 64-Bit Server VM Corretto-8.322.06.1 (build 25.322-b06, mixed mode)
如果把 export JAVA_HOME=$(/usr/libexec/java_home -v $1) 定义在别的脚本文件中要用 source switch_java.sh 1.8 来切换
最后注意在用 /usr/libexec/java_home 定位 JAVA_HOME 时不需要为 JAVA 定制 PATH,要以 /usr/bin/java 作为入口。
javac 也一样
$ which javac
/usr/bin/javac
更多 /usr/bin 下的 java 命令
1 2 3 4 5 6 |
$ ls /usr/bin/j* /usr/bin/jar /usr/bin/javah /usr/bin/jconsole /usr/bin/jhsdb /usr/bin/jmap /usr/bin/jpackage /usr/bin/json_pp /usr/bin/jstack /usr/bin/jarsigner /usr/bin/javap /usr/bin/jcontrol /usr/bin/jimage /usr/bin/jmc /usr/bin/jps /usr/bin/json_pp5.18 /usr/bin/jstat /usr/bin/java /usr/bin/javapackager /usr/bin/jdb /usr/bin/jinfo /usr/bin/jobs /usr/bin/jrunscript /usr/bin/json_pp5.30 /usr/bin/jstatd /usr/bin/javac /usr/bin/javaws /usr/bin/jdeps /usr/bin/jjs /usr/bin/join /usr/bin/jsadebugd /usr/bin/json_xs /usr/bin/jvisualvm /usr/bin/javadoc /usr/bin/jcmd /usr/bin/jhat /usr/bin/jlink /usr/bin/jot /usr/bin/jshell /usr/bin/json_xs5.30 |
如果有 JDK 中无法被 /usr/bin 下 j* 覆盖的命令,就要从 $JAVA_HOME/bin 中找,所以必要时在修改 JAVA_HOME 环境变量后,也应更新 PATH 环境变量。
关于 Linux 下如何找到 JAVA_HOME, 有两个命令
1 2 3 4 |
sh-4.2# dirname $(dirname $(readlink -f $(which javac))) /usr/lib/jvm/java-11-openjdk-11.0.14.1.1-1.el7_9.x86_64 sh-4.2# java -XshowSettings:properties -version 2>&1 > /dev/null | grep 'java.home' java.home = /usr/lib/jvm/java-11-openjdk-11.0.14.1.1-1.el7_9.x86_64 |
链接:
本文链接 https://yanbin.blog/macos-how-to-locatate-java_home/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。