JAVA_HOME and Mac OS X
The purpose of this article is to illuminate how Java is installed and accessed on Mac OS X 10.5 versions and later. If you execute which java
this will output /usr/bin/java
.
This is not where Java resides, it is a symbolic link to /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java
And confusingly enough, this is also not where Java resides. Files contained in /System
tend to be Apple specific and not 3rd party. The second clue, as pointed out by Stack Overflow user bdash [1], are files in: /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands
are on the order of 10 bytes in size. The real Java executable is bigger than that!
Dynamic Tracing
bdash gives the following command to run</a>:
sudo dtrace -n 'syscall::posix_spawn:entry { trace(copyinstr(arg1)); }' -c "/usr/bin/java -version"
This outputs:
dtrace: description 'syscall::posix_spawn:entry' matched 1 probe
dtrace: pid 712 has exited
CPU ID FUNCTION:NAME
0 629 posix_spawn:entry /Library/Java/JavaVirtualMachines/jdk1.7.0_65.jdk/Contents/Home/bin/java
This suggests the Java program resides in
/Library/Java/JavaVirtualMachines/jdk1.7.0_65.jdk/Contents/Home/bin/java
and is indeed correct. Also, to confirm that I have one JDK version, I observe that my directory /Library/Java/JavaVirtualMachines
only contains one directory named jdk1.7.0_65.jdk
Multiple JDK versions are allowed and will reside in /Library/Java/JavaVirtualMachines/
The next question is, how are multiple versions managed? And the answer is java_home
Java Home
Since Mac OS X 10.5, Apple has provided a tool called java_home
. Its function is to dynamically find the Java version a user specifies in Java Preferences [2]. It returns the home path of the current JDK in use. I run this program with help flag:
/usr/libexec/java_home --help
And discover the --verbose
flag. It tells me the full list of JVM architectures I have on my machine. When I run this with this flag on my machine (Macbook OS X 10.10.3) I get the following output:
Matching Java Virtual Machines (1):
1.7.0_65, x86_64: "Java SE 7" /Library/JavaVirtualMachines/jdk1.7.0_65.jdk/Contents/Home
This confirms what I observed earlier in /Library/Java/JavaVirtualMachines
, that I only have one JDK version. Just like /usr/bin/java
, java_home
is a symbolic link to a file that resides in:
/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands
By the way, /usr/libexec
is supposed to a folder that contains binaries meant to be run by other programs (i.e., not users) [3].
Java Applet
There's one last Java version sitting around that should be explained as well. Consider:
/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java
It's not a symbolic link nor a binary that redirects to another file. What is it? The path makes it clear: it's used by Safari when it executes a Java applet. On my machine, it has a newer build. It's a JRE and to the best of my knowledge, it only allows one JRE version to be installed.
JAVA_HOME
Now that we better understand how Java is accessed on the Mac, we'd like to set the environmental variable JAVA_HOME
. Modify your ~/.bash_profile
file:
JAVA_HOME=$(/usr/libexec/java_home)
PATH=$PATH:$JAVA_HOME/bin
export JAVA_HOME
Using java_home
instead of hard-coding a path, will return the path of the Java home directory. We add it to our path variable and finally, export the JAVA_HOME
for use as an environmental variable
As a final note, apparently for versions earlier than 10.5, Apple recommends using the fixed path of /Library/Java/Home
[2].