Understanding Oracle's Java on Mac
Asked Answered
S

3

50

I've been using Java on OS X for many, many years and recently when Apple stopped including Java by default I let the OS go and install it for me (Apple's variety, of course).

So now I'm using OS X 10.8 and I need to install Java 7 so I just got Oracle's Update 15 in DMG form and ran the installer. It updated my /usr/bin/java (and related files) to point here:

/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java

Tracing this back to '/System/Library/Frameworks/JavaVM.framework/Versions' everything either points to 'Current' or 'CurrentJDK', the former being a link to 'A' (which is Oracle's Java 7, from what I can tell, not sure why it is 'A') and the latter being a link to Apple's Java 6 in '/System/Library/Java/JavaVirtualMachines/1.6.0.jdk'.

Now this is all really confusing but this isn't even my question yet. It appears there is a Java 7 installed here:

/System/Library/Frameworks/JavaVM.framework/Versions/A

But there is also a Java 7 installed here:

/Library/Java/JavaVirtualMachines/jdk1.7.0_15.jdk

Finding 'java' in both and printing out the version yields the same version and build (java version "1.7.0_15"), however, when hashing the files they are different.

So does this mean Oracle installed Java 7 in two different places? If so, why? Which am I supposed to use? And why do some things still point to Java 6 (CurrentJDK).

I've looked on Oracle's website but nothing there clears anything up.

Symphonic answered 27/2, 2013 at 19:32 Comment(1)
Asked exactly the same question i want to. I was really confused by the "2" JRE in my Mac. Your description is clear and clean. Thanks for asking:)Justicz
P
79

Oracle's JVM is only installed in one location. You've been misled!

As you've noted, the Java commands in /usr/bin are symlinks to binaries in /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands. The binaries within that directory are stub applications that determine which Java VM to use*, and then exec the corresponding real binary within that VM version. This is why all of the binaries within /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands are almost identical in size, despite the fact that you'd expect them to be implementing quite different functionality.

You can see this in action by using dtrace:

mrowe@angara:~$ sudo dtrace -n 'syscall::posix_spawn:entry { trace(copyinstr(arg1)); }' -c "/usr/bin/java -version"
dtrace: description 'syscall::posix_spawn:entry ' matched 1 probe
dtrace: pid 44727 has exited
CPU     ID                    FUNCTION:NAME
  8    619                posix_spawn:entry   /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java

The given dtrace invocation prints out the path argument to posix_spawn when it is called by java -version. In my case the stub application has found Apple's Java 1.6 runtime in /System/Library/Java/JavaVirtualMachines/1.6.0.jdk and is invoking that version of the java command.

The stub binaries also have another benefit: when they detect that no Java VM is installed they will prompt the user to install one.

As for the CurrentJDK symlink, as best as I can tell this for sake of backwards-compatibility with the past when Apple was the only source of the JVM on OS X.


* A combination of factors are considered when determining which Java VM should be used. JAVA_HOME is used if set (try JAVA_HOME=/tmp java). If JAVA_HOME is not set then the list of all virtual machines on the system is discovered. The JAVA_VERSION and JAVA_ARCH environment variables are used, if set, to filter the list of virtual machines to a particular version and supported architecture. The resulting list is then sorted by architecture (preferring 64-bit over 32-bit) and version (newer is better), and the best match is returned.

Pool answered 28/2, 2013 at 10:40 Comment(2)
Thank you very much, I didn't even think to look at the size of the files. I can investigate a bit more on my own, but where you say "stub applications that determine which Java VM to use" ... how do they make this determination? Hopefully it's with JAVA_HOME but maybe something else?Symphonic
A combination of factors are considered. JAVA_HOME is used if set (try JAVA_HOME=/tmp java). If JAVA_HOME is not set then the list of all virtual machines on the system is discovered. The JAVA_VERSION and JAVA_ARCH environment variables are used, if set, to filter the list of virtual machines to a particular version and supported architecture. The resulting list is then sorted by architecture (preferring 64-bit over 32-bit) and version (newer is better), and the best match is returned.Pool
D
11

The Oracle Java 7 JRE (i.e. the one that is used by the web browser plugin to run applets and Java Web Start) installs itself in /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home, and it is this one that any automatic updates will affect. The JDK (the one you download from http://www.oracle.com/technetwork/java/javase/downloads/index.html) installs by creating a directory under /Library/Java/JavaVirtualMachines, and it's up to you to update this yourself. You can have multiple JDK versions installed side by side but only one "public" JRE under JavaAppletPlugin.plugin (which will correspond to the latest installed JDK or a later version if it has been auto-updated since).

As explained by bdash, the commands under /usr/bin are stubs that delegate to whichever JDK/JRE is pointed to by the JAVA_HOME environment variable, or if that is not set then they will pick the most appropriate Java to run. You can use /usr/libexec/java_home to see which one the stubs would pick. If no Java is installed the stubs will offer to install the latest Apple Java 6 (as far as I know they will not offer to install Java 7).

Diatomite answered 28/2, 2013 at 11:8 Comment(6)
Thanks for the explanation and that makes sense. I'll have to test the JAVA_HOME var and java_home bin to make sure I can get it to work as expected.Symphonic
@Symphonic I realise my answer wasn't perfectly clear - the stubs will always respect JAVA_HOME - running /usr/libexec/java_home shows you which one it would pick if JAVA_HOME were not set.Diatomite
@Pool and Ian really appreciated your answers. I arrived at this post for a DIFFERRENT reason, I managed to mess up my Java install by mangling/misunderstanding the various symlinks and stubs. In case others hit this problem, my errors while running ant were "java.lang.NoClassDefFoundError: Could not initialize class sun.util.calendar.ZoneInfoFile, at sun.util.calendar.ZoneInfo.getTimeZone(ZoneInfo.java:663)" and "There has been an error prior to that: java.lang.AssertionError: Platform not recognized at sun.nio.fs.DefaultFileSystemProvider.create(DefaultFileSystemProvider.java:73)" - Phew!Mauricemauricio
@MarkBennett: This has come full circle. I'm the original poster of this question almost 2 years ago, just got the same error you are getting after installing yosemite, and was led back to my same post! But I can't seem to get this fixed; the 'java_home' command doesn't seem to exist on yosemite. Any suggestions?Symphonic
@Symphonic this is why I'm a bit reluctant to upgrade to Yosemite. I'm sorely tempted, but Java and command line developer tools get messed up every time I do a major upgrade. I'm getting use to it, I know to install Xcode and command line tools, and the absurd command-line accept license thing. But still other times various ancillary tools are messed up too. OS X used to awesome for developers out-of-the-box. I still like it, but it's not how it used to be. I'm sure each change had some rationale, but the sum and direction is sad.Mauricemauricio
@MarkBennett: Yeah, actually, this java issue was my second problem. The first problem is that GD isn't compiled correctly into PHP. I agree, every time I go through problems, but every time I seem to do the upgrade within a few weeks of release. Masochist, I guess. :)Symphonic
L
5

I find this post: https://developer.apple.com/library/mac/qa/qa1170/_index.html The /usr/libexec/java_home tool dynamically finds the top Java version specified in Java Preferences for the current user.

Latitudinarian answered 18/5, 2015 at 9:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.