Setting JAVA_HOME on Mac OS

This was originally posted in 2013 on my mbcdev blog. I’m setting up a new computer, and I figured it was time to update it a bit.

The case of the missing JAVA_HOME

OS X has had a very useful utility, since 2003, that allows you to easily generate a path to a JDK. The simplest usage of the tool will return the default JDK, which in my case is update 131 of JDK 1.8.

➜ ~ /usr/libexec/java_home 
/Library/Java/JavaVirtualMachines/jdk1.7.0_17.jdk/Contents/Home

You can also ask it to list all of your JDKs too by using the -V argument. I have omitted the JDK paths for brevity.

➜ ~ /usr/libexec/java_home -V
Matching Java Virtual Machines (2):
1.8.0_131, x86_64: "Java SE 8"
1.7.0_17, x86_64: "Java SE 7"

You can also do some cool stuff like filter by cpu architecture:

➜ ~ /usr/libexec/java_home -a i386
➜ ~ /usr/libexec/java_home -a x86_64

If that’s a bit wordy for you you can do the same thing by specifying the data model (bits) too:

➜ ~ /usr/libexec/java_home -d 32
➜ ~ /usr/libexec/java_home -d 64

The tool can do some other stuff too and the manual page is clear and concise.

This helps us because we can simply do something like this in our shell configuration files to make JAVA_HOME always point to the latest JDK by default.

export JAVA_HOME=`/usr/libexec/java_home`

This line would typically go in ~/.bashrc if you use bash or ~/.zshrc if you use zsh. You can also put it in /etc/profile if you want it to be available to all users and not just yourself.

Naturally if you don’t want to use the latest and greatest you could specify that you want to use the 64-bit JDK 1.7 like this:

export JAVA_HOME=`/usr/libexec/java_home -d 64 -v "1.7*"`

The back-ticks, `, in the command are important. They capture the output of the java_home command and then that value is assigned to the JAVA_HOME environmental variable. Finally this variable is exported, meaning it will be available to sub-processes.

This is all well and good for terminal work, but graphical apps like IntelliJ IDEA will need some more work. The neatest way that I’ve found to support this is to add another line to your shell configuration like this:

launchctl setenv JAVA_HOME `/usr/libexec/java_home`

The next time you use IntelliJ you’ll see that JAVA_HOME is recognised correctly, and all is well with the world.

JAVA_HOME is now recognised

It goes without saying that these techniques also work with GRADLE_HOME, ANDROID_HOME, and pretty much any environmental variable that you need. Thanks for reading!

Like what you read? Give Barry Carroll a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.