This entry is about JAVA_HOME. (Yep, you read that right.) I never imagined I would ever write a post on an environment variable, but - hey - I have been breaking my jaws on this one for a while, so I figured there are probably a couple of other people happy to learn about the solution.

Now, mind you, this is a problem for people on MacOS only.

I will now take a pause for people cheering and rolling over from laughing.

(I know, I know, I have been zealously preaching Mac and Linux superiority over Windows for as long as I remember...)

Anyway, with that out of the way - this is the problem:

fringe:~ wilfred$ java -version
java version "1.6.0_13"
Java(TM) SE Runtime Environment (build 1.6.0_13-b03-211)
Java HotSpot(TM) 64-Bit Server VM (build 11.3-b02-83, mixed mode)</pre>
fringe:~ wilfred$ mvn -version
Maven version: 2.0.9
Java version: 1.5.0_19
OS name: "mac os x" version: "10.5.7" arch: "i386" Family: "unix"
fringe:~ wilfred$ echo $JAVA_HOME

Can you tell what's going on here? First of all, I run 'java -version', and it tells me its version is 1.6.0_something. Then I run 'mvn -version', and it tells me the version of Java is 1.5.0_something. That's annoying. In fact, it is totally retarded.

The idea is that - on Mac - you set the default versions of Java through some kind of preferences pane. From that point on, everything would just work. No matter how often you would flip back and forward between different versions, it would just be fine. However, that clearly no longer works. It turns out that most Java-based tools on my system get it wrong.

Looking a little further, it turns out that this is the problem:

case "`uname`" in
  CYGWIN*) cygwin=true ;;
  MINGW*) mingw=true;;
  Darwin*) darwin=true 
           if [ -z "$JAVA_VERSION" ] ; then
             JAVA_VERSION="CurrentJDK"
           else
             echo "Using Java version: $JAVA_VERSION"
           fi
           if [ -z "$JAVA_HOME" ] ; then
             JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Home
           fi
           ;;
esac

It turns out that a lot of scripts take /System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Home as the default for JAVA_HOME, and it turns out that this is no longer the location of your current JDK set through the preference pane.

So you need to set JAVA_HOME manually. But how do you do that if you want it to be in line with the JDK selected through your preferences? There just doesn't seem to be a easy way out.

The solution is actually quite simple, but also quite well hidden. Since Java for Mac OS X v10.5 Update 4, there is a new tool in '/usr/libexec' called 'java_home'. And guess what: it by default returns the location of the current version of Java set through the preference pane.

Now, solving the problem outlined above turns out to be fairly easy. You just set JAVA_HOME to the output of this command in your .profile file, and everything works like a charm:

fringe:~ wilfred$ export JAVA_HOME=`/usr/libexec/java_home`
fringe:~ wilfred$ mvn -version
Maven version: 2.0.9
Java version: 1.6.0_13
OS name: "mac os x" version: "10.5.7" arch: "x86_64" Family: "mac"

The interesting thing is: java_home also accepts a whole slew of commandline options. So instead of saying that you want the version of Java listed atop of the preference pane, you can actually make it pick a 64-bit version, a version in a particular range of versions or a version supporting a particular task. I think that's pretty sweet. What do you say?