Manage multiple java version on macOS 11+
Starting from the launch of Java 11, it has been known that Oracle has decided to make money out of its products. With this Oracle will provide two JDK releases, as followed
| Open JDK built under GPL open source
| Oracle JDK which is a paid version
With the recent releases from Oracle, it is predominantly known that Java is evolving being JDK 16.0.1 as its latest at time of posting this article. Being a developer of applications running monolithic to micro services, we may not be able to update the JDKs then and there. But as the platform has updated, we will be using the latest JDK for new application. It’s cumbersome to switch between Java versions when working on ’n’ application running different on different JDKs. So, let’s make it an ease to switch between the environments.
Either coffee or beer, it has to be brewed. Then why the exception for package manager. So, let’s brew
Here’s is a short info about brew package manager as they claim
The Missing Package Manager for macOS (or Linux)
Install brew with command here
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
If you have missed to follow the steps added at end of execution of command, here are the things to be done and this step is specific for Apple's own silicon chip powered machines.
Note: Replace <user_name> with actual username
$ echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/<user_name>/.zprofile $ eval "$(/opt/homebrew/bin/brew shellenv)"
We will be using homebrew/cask through which JDKs will be installed to machine. As they claim to be Homebrew Cask extends Homebrew and brings its elegance, simplicity, and speed to the installation and management of GUI macOS applications such as Atom and Google Chrome. With cask, we can access multiple versions of any kind of softwares.
$ brew tap homebrew/cask
To check successful installation of cask run the following and check the result as list contains homebrew/cask
$ brew tap
Now, we are done with the installation necessary package manager and other installers.
Installing JDK with brew
We have done all the necessary basic setup for installation of JDK. There are certain other tool kits, which can be used directly for managing multiple JDKs.
As they claim to be “SDKMAN! is a tool for managing parallel versions of multiple Software Development Kits on most Unix based systems”
With Homebrew, we will be installing Java JDKs. Oracle has made decision to discontinue older Java version and support for it. And it has also recommended it’s users to stop using it as there will be no bug or security fixes. From version 11 of JDK, Oracle is providing Long term support and we need license to use it. So, we will be going with OpenJDK which is open-sourced Standard Edition and free for usage. OpenJDK is available from version 7 of JDK.
Let’s begin with steps to install JDKs
At Terminal window, to install the latest version of Java JDK which is currently 16
$ brew install --cask oracle-jdk
This will install latest version Java JDK available at the time of execution.
For older versions of Java, we have to tap adoptopenjdk, which uses infrastructure, build and test scripts to produce pre-built binaries from OpenJDK.
$ brew tap adoptopenjdk/openjdk
If you need specific version of Java to be installed, use the following command.
$ brew install --cask adoptopenjdk<version>
Note: Replace <version> with the version that has to be installed.
$ brew install --cask adoptopenjdk8 $ brew install --cask adoptopenjdk9 $ brew install --cask adoptopenjdk11
Now we got multiple java versions added to machine. Next is to set the environment based the project you are working with. There are two cases to be considered, when setting java version. Either it has to local setting or global setting.
Installing jEnv with brew for managing Java environment
jEnv is a command line tool that will help you forget the way to set JAVA_HOME environment variable
As we already got brew package manager, it can be simply installed with the command
$ brew install jenv
After installing jEnv, we have to export this to the system path variable.
For Bash, execute the following commands to add it to .bash_profile
$ echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(jenv init -)"' >> ~/.bash_profile
For Zsh, use the below commands
$ echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.zshrc
$ echo 'eval "$(jenv init -)"' >> ~/.zshrc
If you are continuing with the same terminal window, latest bash_profile or zshrc has to be sourced. This can be done with the command
$ source ~/.bash_profile
$ source ~/.zshrc
Or else, you can open the new terminal window which will refresh the profile.
Then comes the way to add your various installed version of Java to jEnv. You will be able to see all the installed version and path of JDK using the command here
$ /usr/libexec/java_home -V
Output will be as followed
We have to tag this paths to jEnv with the command
$ jenv add <path-of-jdk>
For illustrating with the above version of JDK been installed to machine, command has to be like
$ jenv add /Library/Java/JavaVirtualMachines/jdk-16.0.1.jdk/Contents/Home $ jenv add /Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home $ jenv add /Library/Java/JavaVirtualMachines/adoptopenjdk-9.jdk/Contents/Home $ jenv add /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
Yey! Now we have added the various version of java to jEnv. Let’s find the various version of Java added to jEnv
$ jenv versions
Output will be like
* system (set by /Users/<user-name>/.jenv/version) 1.8 18.104.22.1682 11 11.0 11.0.11 16 16.0 16.0.1 9 openjdk64-22.214.171.1242 openjdk64-11.0.11 openjdk64-9 oracle64-16.0.1
Yes, you will see some duplicate versions which will make the next step easier. We may have to un-tag certain version of JDK from jEnv which can be done by
$ jenv remove <version>
If I want to remove version oracle64-126.96.36.1991, command would be like
$ jenv remove oracle64-188.8.131.521
Yey!, lets define the JDK to be used. It can be done with the following command
$ jenv <scope> <version>
<scope> can either be local or global, which defines the scope of JDK being configured. If you have to set it only to local directory you can go with local or if you want to set the version globally, set the scope to global
Illustration with above version of JDKs been tagged to jEnv
$ jenv global 16.0
This will set my global version of Java used by machine
$ jenv local 1.8
This will set Java version that’s used with the directory or the folder of project where in which command is ran
Check the version that has been added to project directory by
$ java -version
Yes! Most things are done now. Lets make it much more simpler to set java version through alias scripts
$ echo 'alias jg="jenv global"' >> ~/.bash_profile $ echo 'alias jl="jenv local"' >> ~/.bash_profile
$ echo 'alias jg="jenv global"' >> ~/.zshrc $ echo 'alias jl="jenv local"' >> ~/.zshrc
Then refresh the profile using source command
$ source ~/.bash_profile
$ source ~/.zshrc
Now we will be able to set the java version globally with
$ jg <version>
And locally with
$ jl <version>
You can define alias based on your need, but make sure it’s not duplicating with aliases added to your machine.
Great! Multiple java JDKs is configured to machine. Now with much ease we will be able the run both the older and latest version of Java with much more flexibility.