Cristian Chiovari is a Senior Software Engineer specialized in developing enterprise software applications with experience on software integration and messaging. His expertise include helping clients build software using industry best practices, Test Driven Design, Weblogic, Oracle Service Bus , Spring Frameworks, JEE. Performance improvements is something that is really passionate about and considers software development not only his job but also his main hobby. Cristian is a DZone MVB and is not an employee of DZone and has posted 10 posts at DZone. You can read more from them at their website. View Full User Profile

Juggling Multiple Versions of Java on OS X Mountain Lion

09.18.2012
| 27457 views |
  • submit to reddit

Prior to Mountain Lion, Java was bundled with OSX. It seems that during the upgrade, the Java 6 version I had on my machine was removed, apparently due to a security issue with the Java runtime. This means you're forced to install the latest version, which fixed this security problem.

So I went to /Applications/Utilities/ open a Terminal and executed the following command:
java -version ==> "No Java runtime present…" A window prompted asking to install Java.Click “Install” and get the latest version.I installed it but right after I downloaded and installed the JDK SE 7 from Oracle.

After installation, open the Java Preferences (Launchapad/Others ) and you will see:

Now I knew I had two versions of Java, but which one am I using?

$ java -version
java version "1.6.0_35"
Java(TM) SE Runtime Environment (build 1.6.0_35-b10-428-11M3811)
Java HotSpot(TM) 64-Bit Server VM (build 20.10-b01-428, mixed mode)

So what if I want to use JDK SE 7 from Oracle?

Then I just had to drag Java SE 7 in the Java Preferences window to the first position in the list.

This time:

$ java -version
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b06)
Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)

I said to myself, "Let’s find out more out how Java is installed on OS X." So I dug for more.

There are some very useful commands: whereis and which and ls -l.

whereis java ==> /usr/bin/java
ls -l /usr/bin/java ==> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java

When I saw this I was a little bit curious so I went to list the Versions directory:

cd /System/Library/Frameworks/JavaVM.framework/Versions
ls ==>
1.4 1.5 1.6 A CurrentJDK
1.4.2 1.5.0 1.6.0 Current

Now why do I have this old versions of Java on my machine? I asked on Ask Different:
http://apple.stackexchange.com/questions/57986/multiple-java-versions-support-on-os-x-and-java-home-location

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.8.1
BuildVersion:	12B19
$ ls -l /System/Library/Frameworks/JavaVM.framework/Versions
total 64
lrwxr-xr-x  1 root  wheel   10 Sep 16 15:55 1.4 -> CurrentJDK
lrwxr-xr-x  1 root  wheel   10 Sep 16 15:55 1.4.2 -> CurrentJDK
lrwxr-xr-x  1 root  wheel   10 Sep 16 15:55 1.5 -> CurrentJDK
lrwxr-xr-x  1 root  wheel   10 Sep 16 15:55 1.5.0 -> CurrentJDK
lrwxr-xr-x  1 root  wheel   10 Sep 16 15:55 1.6 -> CurrentJDK
lrwxr-xr-x  1 root  wheel   10 Sep 16 15:55 1.6.0 -> CurrentJDK
drwxr-xr-x  7 root  wheel  238 Sep 16 16:08 A
lrwxr-xr-x  1 root  wheel    1 Sep 16 15:55 Current -> A
lrwxr-xr-x  1 root  wheel   59 Sep 16 15:55 CurrentJDK -> /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents

It seems all the old versions are links to the CurrentJDK version, which is the Apple version, except A and Current which is linked to A. I read something about this on this question. For me, A acts like a temp variable. If in Java Preferences you set this in the first position, Java 6 from Apple A will have Java 6 from Apple. If you put on the first position Java SE 7 from Oracle, A will point to this version. Current points to A.

/java -version
java version "1.6.0_35"
Java(TM) SE Runtime Environment (build 1.6.0_35-b10-428-11M3811)
Java HotSpot(TM) 64-Bit Server VM (build 20.10-b01-428, mixed mode)
./java -version
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b06)
Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)

This means that this current directory will point to the first Java Version found in the Java Preferences. Now take a look at the following:

lrwxr-xr-x  1 root  wheel   59 Sep 16 15:55 CurrentJDK -> /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents

This means Java from Apple is actually installed here: "/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/"

What about Java SE 7? I could search the filesystem to see, but I found an easier way:

If, in Java Preferences, Java SE 7 is in the first position ==>

$ /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home

If Java SE 6 (System) is in the first position ==>

$ /usr/libexec/java_home
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

So Java on Mountain Lion (OSX) is more likely to be installed in one of these locations:

  • /System/Library/Java/JavaVirtualMachines
  • /Library/Java/JavaVirtualMachines
  • ~/Library/Java/JavaVirtualMachines

What about /System/Library/Frameworks/JavaVM.framework/Versions? It seems like this is linked to the so-called "Java bridge." Here it seems to be the native part of the Java on OSX installation.

 

Published at DZone with permission of Cristian Chiovari, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

David Whatever replied on Tue, 2012/09/18 - 8:22pm

The symlink contents of JavaVM.Framework are a historical relic. There was a time when Apple actually shipped all those JVMs and applications would link against them directly; when they were finally obsoleted and no longer shipped those versions, they just symlinked to the closest one. I think as of 10.6, they stopped shipping anything other than Java 6. I believe the entire JavaVM.Framework is now a facade for one of the installed JVMs.

Java on OS X now uses vendor bundles with a .jdk extension, installed in one of the three locations described above (/System/Library for the version which is considered part of the OS, /Library for system-wide and ~/Library for per-user). The Java Preferences exposes them to the environment in the specified order (hence the onscreen instruction to drag to reorder them).

The default java application will by default delegate to installed java implementations in preferred order. You can override its behavior simply by setting JAVA_HOME. For Oracle's 1.7 JDK:

export JAVA_HOME=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/

 Also useful is the /usr/libexec/java_home command. Using this you can query and filter the list of JVMs which are installed, or launch commands using an installed version of java that meets your requirements. It is also the way to request Apple's Java be installed from installers, and gives you a XML plist representation of the JVMs which are available.

Finally, unless they changed it (I haven't used JNI myself to embed java in a native application since 10.5) the system version of the java native libraries you link apps are facades just like the command-line apps, which pay attention to the system-defined order and JAVA_HOME environment variable.

Cristian Chiovari replied on Wed, 2012/09/19 - 12:02am

Overriding the behaviour via setting JAVA_HOME is something that was not covered in my article.

Thanks for pointing that.

A very nice article about this topic which has more focus on JAVA_HOME is here :

http://blog.hgomez.net/2012/07/20/understanding-java-from-command-line-on-osx/ 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.