Running Multiple Versions of Java on MacOS with jenv

jenv makes it easy to run multiple versions of Java on a Mac computer. It also makes it easy to seamlessly switch between Java versions when you switch projects.

Running multiple Java versions is important for Android and Apache Spark developers. Spark developers should use Java 8 for Spark 2 projects and Java 11 for Spark 3 projects for example.

This blog post shows you how to get jenv setup on your computer and how to use the important commands.

jenv setup

Install jenv with brew install jenv. This is a Homebrew command.

jenv uses the shim design pattern to route commands to the appropriate Java version. Run these commands to update your PATH:

echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(jenv init -)"' >> ~/.zshrc

Restart your Terminal, run echo $PATH, and verify the output contains .jenv paths that are prepended to the standard PATH directories. Here’s the output on my machine /Users/powers/.jenv/shims:/Users/powers/.jenv/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin.

Install Java 8

Here’s the latest command to install Java 8: brew cask install adoptopenjdk/openjdk/adoptopenjdk8.

brew cask install adoptopenjdk8 used to work, but now returns Error: Cask 'adoptopenjdk8' is unavailable: No Cask with this name exists.

brew cask install caskroom/versions/adoptopenjdk8 also used to work, but now returns Error: caskroom/versions was moved. Tap homebrew/cask-versions instead.

Once Java is downloaded, we need to manually add it to jenv. List the Java virtual machines with ls -1 /Library/Java/JavaVirtualMachines.

Add Java 8 to jenv with jenv add /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/.

Set the global Java version on your computer with jenv global openjdk64-1.8.0.265. The exact command on your machine might be something slightly different like jenv global openjdk64-1.8.0.272. Find the exact name of the version with jenv versions.

Check to make sure the javac -version and java -version commands are working.

Set global Java version

Macs come with Java preinstalled. It’s always good to avoid using system installed programming language versions (applies to Python and Ruby too). jenv makes it easy to avoid using the system Java.

Set the global Java version to Java 8 with jenv global openjdk64-1.8.0.265.

This command simply writes the version to the /Users/powers/.jenv/version file. Type cat /Users/powers/.jenv/version to see it’s just a file with a single line

openjdk64-1.8.0.272

All Java commands will be routed to Java 8 now that the global version is set. This’ll make sure we avoid hitting the system Java version.

Set JAVA_HOME

Lots of Java libraries depend on having a JAVA_HOME environment variable set. Set the environment variable by running these commands:

jenv enable-plugin export
exec $SHELL -l

Run echo $JAVA_HOME and verify that it returns something like /Users/powers/.jenv/versions/openjdk64-1.8.0.272. Now any library that’s looking for the JAVA_HOME environment to be set won’t error out.

Run jenv doctor to confirm your setup is good. You should get output like this:

[OK]    JAVA_HOME variable probably set by jenv PROMPT
[OK]    Java binaries in path are jenv shims
[OK]    Jenv is correctly loaded

Install Java 11

Here’s the command to install Java 11: brew cask install adoptopenjdk/openjdk/adoptopenjdk11.

Remember that Java versions need to be manually added to jenv. List the Java virtual machines with ls -1 /Library/Java/JavaVirtualMachines.

Add Java 11 to jenv with jenv add /Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home/.

The jenv versions command should now output this:

  system
  1.8
  1.8.0.272
  11
  11.0
  11.0.9
* openjdk64-1.8.0.272 (set by /Users/powers/.jenv/version)
  openjdk64-11.0.9

Setting up Maven

which mvn returns /usr/local/bin/mvn, which is the system version of Maven. Similar to Java, we never want to run commands using the system Maven. Let’s use jenv to get a different version of Maven.

Enable the jenv Maven plugin with jenv enable-plugin maven and then run which mvn to verify that the mvn commands are being properly captured by a jenv shim. The which mvn command should return something like /Users/powers/.jenv/shims/mvn.

You can verify that your Maven installation is working properly by cloning a project and running the test suite. Clone the JavaSpark project with the git clone git@github.com:MrPowers/JavaSpark.git command.

cd into the project directory and run the test suite with mvn test.

You can type mvn -v to see the Maven version that’s being used. My machine is using Maven 3.6.3 with Java 8.

You can also clone the deequ repo and verify that mvn test is working on that repo as well.

Setting local Java version for projects

Use the jenv local openjdk64-11.0.9 command to set a given project to use Java 11 by default.

This will add a .java-version file in the root project folder. Here’s an example.

You can clone the delta-examples repo with git clone git@github.com:MrPowers/delta-examples.git, cd into the directory, and run jenv versions to verify that the project is automatically using Java 11.

Here’s the jenv versions output from the delta-examples project root directory:

  system
  1.8
  1.8.0.272
  11
  11.0
  11.0.9
  openjdk64-1.8.0.272
* openjdk64-11.0.9 (set by /Users/powers/Documents/code/my_apps/delta-examples/.java-version)

jenv’s ability to automatically switch Java versions for different projects is quite convenient. You don’t need to think about manually setting the Java version when you change projects.

Other ways to switch Java versions

The AdoptOpenJDK project provides guidance on how to manually switch between Java versions if you don’t want to use jenv. Here’s the function they provide:

jdk() {
        version=$1
        export JAVA_HOME=$(/usr/libexec/java_home -v"$version");
        java -version
 }

Switching manually is possible, but who wants to waste mental energy thinking about Java versions every time they switch a project?

Next steps

jenv will help you manage Java on your Mac, even if you only need to use a single version.

Managing different Java versions on a given machine was a huge pain before jenv came along. Now, you only need to run a few commands and your machine can be configured to run any Java version. jenv makes it easy to avoid accidentally using the system installed Java packages.

jenv has built in plugins for SBT, Scala, Groovy, and more. Make sure to enable the plugins that are relevant for your workflows.

Leave a Reply

Your email address will not be published. Required fields are marked *