1. Introduction

With every new release cycle of Java, we might need to manage multiple parallel versions of the Software Development Kits (SDKs) in our environment. So setting and managing the JAVA_HOME path variable can become a real pain at times.

In this tutorial, we’ll see how jEnv can help manage multiple different versions of JDK installations.

2. What Is jEnv?

jEnv is a command line tool that helps us manage multiple JDK installations. It basically sets JAVA_HOME inside our shell in a way that can be set globally, locally to the current working directory, or per shell.

It lets us quickly switch between different Java versions. This is particularly helpful when working with multiple applications having different Java versions.

It’s worth noting that jEnv doesn’t install the Java JDK for us. Instead, it just helps us conveniently manage multiple JDK installations.

Further, let’s deep dive into jEnv installation and review its most common commands.

3. Installing jEnv

jEnv supports Linux and MacOS operating systems. Moreover, it supports Bash and Zsh shells. Let’s begin by installing it using the terminal:

On MacOS, we can simply install jEnv using Homebrew:

$ brew install jenv

On Linux, we can install jEnv from the source:

$ git clone https://github.com/jenv/jenv.git ~/.jenv

Next, let’s add the installed jenv command to the path based on the shell being used.

Adding PATH entry for Bash shell:

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

Adding PATH entry for Zsh shell:

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

Lastly, to verify the jEnv installation, we make use of the jenv doctor command. On MacOS, the command would display the following:

$ jenv doctor
[OK]    No JAVA_HOME set
[ERROR]    Java binary in path is not in the jenv shims.
[ERROR]    Please check your path, or try using /path/to/java/home is not a valid path to java installation.
    PATH : /opt/homebrew/Cellar/jenv/0.5.4/libexec/libexec:/Users/jenv/.jenv/shims:/Users/user/.jenv/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
[OK]    Jenv is correctly loaded

This indicates that jenv is correctly installed and loaded, but Java isn’t yet installed.

Further, let’s take a look at how we can install and manage multiple JDK versions.

4. Managing JDK Installations

Let’s start by setting up a JDK version. We can install the JDK with one of the available package managers like brew, yum, or apt. Alternatively, we can also download the JDK and put it in some folder.

The good thing about jEnv is that we don’t need to install the JDK via a package manager. We can simply download a JDK and put it into a folder somewhere.

4.1. Adding a JDK to jEnv

Firstly, to use the new JDK with jEnv, we need to tell jEnv where to locate it. To do this, we make use of the jenv add command and specify the path to the JDK:

$ jenv add /Library/Java/JavaVirtualMachines/openjdk-8.jdk/Contents/Home/
openjdk8-1.8.0.332 added
1.8.0.332 added
1.8 added

This will add JDK 8 to jEnv. Each version is available under three different names. Let’s run jenv doctor again to confirm the JDK setup:

$ jenv doctor
[OK]    No JAVA_HOME set
[OK]    Java binaries in path are jenv shims
[OK]    Jenv is correctly loaded

We can see that jEnv now recognizes the configured JDK.

Further, let’s list all the available JDKs with jEnv using the jenv versions command:

$ jenv versions
* system (set by /Users/user/.jenv/version)
  1.8
  1.8.0.332
  openjdk64-1.8.0.332

This lists all the JDK registered with jEnv. In our case, we have JDK 8 configured with jEnv.

To demonstrate using multiple JDKs, let’s install one more JDK version – 11 and configure it with jEnv:

$ jenv add /Library/Java/JavaVirtualMachines/openjdk-11.jdk/Contents/Home/
openjdk64-11.0.15 added
11.0.15 added
11.0 added
11 added

Lastly, Running jenv versions command now will list both the configured JDK versions:

$ jenv versions
* system (set by /Users/avinb/.jenv/version)
  1.8
  1.8.0.332
  11
  11.0
  11.0.15
  openjdk64-11.0.15
  openjdk64-1.8.0.332

Evidently, we now have both the JDK versions configured with jEnv.

4.2. Managing JDK Versions Using jEnv

jEnv supports three types of JDK configuration:

  • Global – JDK that will be used if we type the java command into the command line anywhere on our computer.
  • Local – JDK that is configured for a specific folder only. Typing the java command in the folder will use the local JDK version instead of the global JDK version.
  • Shell – JDK that will be used only for the current shell instance.

Firstly, let’s check the version of the global JDK:

$ jenv global
system

Checking the global version now will display JDK 11:

$ jenv global
11

Next, let’s look at how we can set a local JDK version.

For example, let’s say we have a sample project in the ~/baeldung-project directory which uses JDK 8. Let’s cd into this directory and check the local JDK version for this project:

$ jenv local
jenv: no local version configured for this directory

This error message indicates that we have not yet set any local JDK version for this directory. Running the jenv version command in the absence of a local JDK version will display the global JDK version. Let’s set a local JDK version for this directory:

$ jenv local 1.8

This command sets the local JDK in the ~/baeldung-project directory. Setting the local JDK basically creates a file called .java-version in the current directory. The file contains the local JDK version “1.8″ which we have set.

Running the jenv version command again in this directory will now output JDK 8. Let’s check the local JDK version set in this directory:

$ jenv local
1.8

Lastly, to set the JDK version for a particular shell instance, we use the jenv shell command:

$ jenv shell 1.8

This sets the JDK version for the current shell instance and overrides any local and global JDK version already set.

4.3. Configure jEnv with Maven and Gradle

As we all know, tools like Maven and Gradle use the system JDK to run. It does not use the jEnv configured JDK. In order to ensure that jEnv works properly with Maven and Gradle, we have to enable their respective plugins.

For Maven, we will enable the jEnv maven plugin:

$ jenv enable-plugin maven

Similarly, for Gradle, we will enable the jEnv gradle plugin:

$ jenv enable-plugin gradle

Running the Maven and Gradle commands now will use the jEnv-specific JDK versions instead of the system JDK.

Note that, sometimes jEnv might not pick the correct JDK version, and we might end up with errors. For such cases, we might have to enable the jEnv export plugin:

$ jenv enable-plugin export

In other words, this plugin will ensure that the JAVA_HOME variable is set correctly.

Also, SDKMAN is an alternative tool for managing JDKs, among other tools.

5. Conclusion

In this article, we first looked at what jEnv is and how we could install it.

We then looked at how jEnv can help us configure and manage different JDK installations conveniently. Next, we saw how we can quickly use a global, local, and shell-specific JDK version using jEnv. This will particularly help us when working with multiple different projects having different JDK versions.

Finally, we looked at how jEnv can be configured to work with build tools like Maven and Gradle.