Multiple JDK versions on Mac OS X with jEnv

Daniel Nenkov
3 min readNov 9, 2017
Java and Docker

I bought a new laptop recently and had to set it up for development. I installed JDK with brew which downloaded and configured Java 9. I knew I will have to stick to Java 8 at least for a bit but decided to rely on Java's famed backward compatibility.

I had a plain sailing for about a week, mostly because I haven’t fully switched to the new machine. However, the first time I started doing something a bit more serious I stumbled upon some problems.

Spring boot, Docker and Java 9

I decided to use the fantastic Spring Boot tutorial and create a project and a corresponding docker image. On my first build I encountered the following problem:

[ERROR] Failed to execute goal com.spotify:dockerfile-maven-plugin:1.3.6:build (default) on project esae-notes: Execution default of goal com.spotify:dockerfile-maven-plugin:1.3.6:build failed: An API incompatibility was encountered while executing com.spotify:dockerfile-maven-plugin:1.3.6:build: java.lang.ExceptionInInitializerError: null

A quick google search made me realise that I am not the first person to ever experience this (it is rarely the case anyway) and I discovered this thread.

In summary:

The problem seems to be related with codehaus-plexus:plexus-archiver

dockerfile-maven-plugin depends on org.apache.maven:maven-archiver:3.0.0 which depends on org.codehaus.plexus:plexus-archiver:2.9.1

This problem is already fixed on plexus-archiver. So, upgrading that dependency should fix the issue.

And also:

It turned out that Java 9 is also missing the javax.activation package which produces a lot of errors. Explicitly adding javax.activation-api:1.2.0 fixes these errors as well.

The fix seems easy enough, all I had to do was to update plugin configuration in maven:

<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<repository>test/${project.artifactId}</repository>
<tag>${project.version}</tag>
</configuration>
<executions>
<execution>
<id>build-image</id>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-archiver</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>javax.activation-api</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>
</plugin>

This got me thinking. If I started having problems with Java 9 during the first more “serious” task I undertook, maybe I should wait a bit until fully switching to it. Also this seems like a great opportunity to try jEnv.

Multiple JDK versions management with brew and jEnv

Step 1: Installing Java 8

If you have installed Java with brew cask install java you will notice that brew installs the latest stable release of Java, which at the time of this writing is Java 9. To install Java 8 you can use:

$ brew cask install java8

If this command doesn’t work and brew can't find the Java 8 package, try this first:

$ brew tap caskroom/versions

Step 2: Installing and configuring jEnv

The first step is to install jEnv which on Mac OS X is done easily with:

$ brew install jenv

Next you have to update your Bash (or Zsh) profile:

Bash
$ echo ‘export PATH=”$HOME/.jenv/bin:$PATH”’ >> ~/.bash_profile
$ echo ‘eval “$(jenv init -)”’ >> ~/.bash_profile
$ source ~/.bash_profile
Zsh
$ echo ‘export PATH=”$HOME/.jenv/bin:$PATH”’ >> ~/.zshrc
$ echo ‘eval “$(jenv init -)”’ >> ~/.zshrc
$ source ~/.zshrc

Then you have to add the Java versions to jEnv:

$ jenv add /Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home/

You can see all versions with:

$ jenv versions
system
1.8
* 1.8.0.152 (set by ~/.jenv/version)
9
oracle64–1.8.0.152
oracle64–9

The * indicates the active version. It can be changed by typing:

$ jenv global oracle64–1.8.0.152

You can also configure a local version (per directory) or a shell instance version by replacing global with local or shell respectively.

Optional Step 3: Configure maven to work with the Java version specified by jEnv

After making sure that java -version shows the correct Java version I tried rebuilding my project with mvn clean install. Unfortunately the build failed again with the same problem.

By running mvn -version I quickly realised that maven is still using Java 9. To make maven use the Java version configured by jEnv I had to run the following:

$ echo ‘JAVA_HOME=$(/usr/libexec/java_home -v $(jenv version-name))’ >> ~/.mavenrc
$ source ~/.mavenrc

--

--