java_home
and JAVA_HOME
on macOS
Ever wondered where Java stuff lives on your Apple Mac? Ever had to find how to set your environment to work with a specific version of Java? Ever manually set the JAVA_HOME
environment variable to get something working?
If so, this note may help.
macOS is the operating system that runs on Apple Mac hardware. I have used Java on these machines for many years. A lot of things have changed in that time: Apple used to bundle Java; Oracle bought Sun; Apple stopped bundling Java … macOS was previously known as Mac OS X and later OS X. Oracle still use the old OS X branding.
I have just installed the latest Java upgrade and decided to try to understand how to work with the different versions of Java on macOS. Then I decide to write about it!
I read JDK 8 Installation for OS X from the Java Platform SE Installation Guide some time ago. But I failed to appreciate the java_home
command.
This Note for Geeks:
- describes how to use
java_home
to set theJAVA_HOME
environment variable - describes how the
java_home --exec <command>
can be used to execute Java commands for a specific JDK version independent ofJAVA_HOME
- describes a bash profile to enable interactive setting of the JDK version
- shares some observations on Java symbolic links on macOS
- is relevant to Java on macOS and versions of OS X since 2012
See Oracle OS X Platform Install FAQ for further information.
ORACLE — IMPORTANT INFORMATION REGARDING THE SECURITY OF JAVA SE
Earlier versions of Java SE have serious security risks corrected in later versions.
That creates a serious security vulnerability. Even if you installed the most recent version of Java SE, the personal information on your computer may be at risk because earlier, less secure versions could still be executed.
To fix this problem, visit http://java.com/uninstall, where instructions on how to uninstall older versions of Java SE are provided.
java_home
/usr/libexec/java_home
is the simplest maintainable way of setting JAVA_HOME
on macOS.
You can use java_home
to:
- Find all installed JDKs
- Get value for
JAVA_HOME
for a specific JDK version - Get the value of
JAVA_HOME
for the default JDK version - Execute specific versions of Java commands
Finding all installed JDKs
$ /usr/libexec/java_home -V
Matching Java Virtual Machines (4):
1.8.0_121, x86_64: "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home
1.7.0_45, x86_64: "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_45.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
NOTE: I will consider uninstalling the 1.6 versions to remove any associate security vulnerabilities
Getting values for JAVA_HOME
for specific JDK versions
$ /usr/libexec/java_home -v 1.6
/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
$ /usr/libexec/java_home -v 1.7
/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home
$ /usr/libexec/java_home -v 1.8
/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home
Getting the value of JAVA_HOME
for the default JDK version
$ /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home
Executing specific versions of Java commands, such as java
java_home
is the best way on macOS to execute a Java command ...jdk/Contents/Home/bin/<command>
for a specific version of the JDK. And it is independent of the setting of JAVA_HOME
.
- Executing the default version of a java
<command>
/usr/libexec/java_home --exec <command>
For example:
$ /usr/libexec/java_home --exec java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
- Executing a specific version of java command
$ /usr/libexec/java_home -v 1.6 --exec java
For example:
$ /usr/libexec/java_home -v 1.6 --exec java -version
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-468-11M4833)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-468, mixed mode)
man java_home
java_home(1)
NAME
java_home - return a value for $JAVA_HOME
-v or --version version
Filters the returned JVMs by the major platform version in "JVMVersion" form.
Example versions: "1.5+", or "1.6*".
-V or --verbose
Prints the matching list of JVMs and architectures to stderr.
--exec command ...
Executes the command at $JAVA_HOME/bin/<command> and passes the remaining arguments.
Any arguments to select which $JAVA_HOME to use must precede the --exec option.
NOTE: The use of
$JAVA_HOME
in the man page is misleading because:
java_home
can be used to return a value that can be used to set$JAVA_HOME
The
--exec command
can be used to execute a command.../Home/bin/<command>
as if it was$JAVA_HOME/bin/<command>
without changing or using$JAVA_HOME
.
JAVA_HOME
The JAVA_HOME
environment variable contains the home location of an installed JDK.
/usr/libexec/java_home
is the simplest maintainable way of setting JAVA_HOME
.
- Set
JAVA_HOME
to JDK version 1.7
export JAVA_HOME=`/usr/libexec/java_home -v 1.7`
- Set
JAVA_HOME
to the default JDK
export JAVA_HOME=`/usr/libexec/java_home`
- Check
JAVA_HOME
$ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home
- Check the actual java version
$ java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
Independence of java_home --exec
from $JAVA_HOME
java_home --exec <command>
can be used to execute Java commands independent of the setting of $JAVA_HOME
.
The following examples demonstrate executing three different versions of the java command without changing $JAVA_HOME
:
- version using
$JAVA_HOME
$ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
$ java -version
java version "1.6.0_65"
- specific version using
java_home --exec java -v 1.7
$ /usr/libexec/java_home -v 1.7 --exec java -version
java version "1.7.0_45"
- default version using
java_home --exec java
$ /usr/libexec/java_home --exec java -version
java version "1.8.0_121"
How I use java_home
to set JAVA_HOME
This setup is for bash, the Bourne Again Shell on macOS. There are similar variations for other shells.
Set environment variables in .bash_profile
# aliase commands to enable easy setting of JDK version
alias setJDK6='export JAVA_HOME=`/usr/libexec/java_home -v 1.6`'
alias setJDK7='export JAVA_HOME=`/usr/libexec/java_home -v 1.7`'
alias setJDK8='export JAVA_HOME=`/usr/libexec/java_home -v 1.8`'
# set to the default JDK
export JAVA_HOME=`/usr/libexec/java_home`
This profile creates aliases to enable interactive setting of the JDK version and sets JAVA_HOME
to the default JDK.
Use the aliases to interactively set JAVA_HOME
Set JAVA_HOME
to v 1.7
$ setJDK7
Check $JAVA_HOME
$ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home
Check java version
$ java -version
java version "1.7.0_45"
Set JAVA_HOME
to v 1.8
$ setJDK8
Check $JAVA_HOME
$ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home
Check java version
$ java -version
java version "1.8.0_121"
I got the idea for the aliases from https://wimdeblauwe.wordpress.com/2014/03/20/switching-easily-between-java-jdks-on-mac-os-x/.
Java symbolic links on macOS
I have been lost a few times trying to follow the symbolic linking of Java versions in and out of /System/Library/Frameworks/JavaVM.framework/Versions/
and /Library/Java/JavaVirtualMachines/
.
The following are what seem to matter.
Which java
$ which java
/usr/bin/java
java
symlink
The java
command is symlinked deep in the JavaVM.framework
$ ls -l /usr/bin/java
/usr/bin/java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java
java_home
symlink
The java_home
command is symlinked deep in the JavaVM.framework
$ ls -l /usr/libexec/java_home
/usr/libexec/java_home -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java_home
Assumption
The Java commands in /usr/bin/
appear to execute the corresponding Java commands for JAVA_HOME
.
Each Java command /usr/bin/<command>
executes $JAVA_HOME/bin/<command>
For example:
/usr/bin/java
executes $JAVA_HOME/bin/java