This is not a naïve question; please bear with me.
Can someone tell me how an invocation of /usr/bin/java
on an Apple MacBook Pro from mid-2010 with both the Apple JDK and the Oracle 1.8.0 JDK installed results in the Oracle 1.8.0 JDK being found and used?
Please note that my version of the Apple-installed JDK 1.6 is recent enough that the Java Preferences application has been removed by them, so that does not factor into the determination of which Java VM to use.
Furthermore please note that /usr/libexec/java_home
is not invoked (by me, anyway) in any of my examples below.
OK, here we go.
Oracle's JDK 1.8 gets installed into /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/
. Fine.
/usr/bin/java
, which is under Apple control, is a symbolic link pointing to /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java
. (/System/Library/Frameworks/JavaVM.framework/Versions/Current
is a symbolic link pointing to /System/Library/Frameworks/JavaVM.framework/Versions/A
(a directory), so, by extension, /usr/bin/java
after symbolic link resolution points to /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java
.)
/System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java
is not a symbolic link. It is an executable. Its last modified timestamp is quite old, probably corresponding to when I installed JDK 7 some time ago. In any event, it does not correspond to the date on which I installed JDK 8.
/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/bin/java
is not equal in size to /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java
. It is not a symbolic link either. Its last modified timestamp corresponds to when I installed JDK 8. These two are different programs.
Nevertheless, invoking either of these java
variants with a -version
argument yields a version string identifying them as 1.8.
How is the semantic link established between /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java
and /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/bin/java
, given that neither is a symbolic link to the other?
Secondly, who "owns" /System/Library/Frameworks/JavaVM.framework/Versions/A
: Oracle or Apple?
Furthermore, consider the following output, especially the argv[0]
setting identifying /usr/bin/java
as the program name, even though I never typed that (line 13 in the output below):
Laird-Nelsons-MacBook-Pro:repository ljnelson$ env _JAVA_LAUNCHER_DEBUG=true /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java -version
----_JAVA_LAUNCHER_DEBUG----
Launcher state:
debug:on
javargs:off
program name:java
launcher name:java
javaw:off
fullversion:1.8.0-b132
dotversion:1.8
ergo_policy:DEFAULT_ERGONOMICS_POLICY
Command line args:
argv[0] = /usr/bin/java
argv[1] = -version
JRE path is /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre
jvm.cfg[0] = ->-server<-
jvm.cfg[1] = ->-client<-
69 micro seconds to parse jvm.cfg
Default VM: server
Does `/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/lib/server/libjvm.dylib' exist ... yes.
----_JAVA_LAUNCHER_DEBUG----
Launcher state:
debug:on
javargs:off
program name:java
launcher name:java
javaw:off
fullversion:1.8.0-b132
dotversion:1.8
ergo_policy:DEFAULT_ERGONOMICS_POLICY
Command line args:
argv[0] = /usr/bin/java
argv[1] = -version
JRE path is /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre
jvm.cfg[0] = ->-server<-
jvm.cfg[1] = ->-client<-
33 micro seconds to parse jvm.cfg
Default VM: server
Does `/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/lib/server/libjvm.dylib' exist ... yes.
JVM path is /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/lib/server/libjvm.dylib
2242 micro seconds to LoadJavaVM
JavaVM args:
version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 4
option[ 0] = '-Dsun.java.launcher.diag=true'
option[ 1] = '-Dsun.java.launcher.diag=true'
option[ 2] = '-Djava.class.path=.'
option[ 3] = '-Dsun.java.launcher=SUN_STANDARD'
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)
/System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java
and/usr/libexec/java_home
end up invoking a private framework calledJavaLaunching
, which is undocumented. Runningstrings
on it suggests that it does a simple stupid scan (!) of/Library/Java/JavaVirtualMachines
and then uses some (undocumented) heuristic to figure out which is the most recent. Ugly and surprising.