With the relatively recent change in the frequency of Java releases (every six months) it has become pretty much required to be able to have multiple JDKs on one’s development machine, and being able to run/test them at different times, for different projects, or even for the same project.

Motivation
While some wizardry with symlinks and similar hackery is possible, on Ubuntu the alternatives
system allows a relatively simpler approach.
If one contents oneself with simply having java
and javac
with alternatives[0], it is simply a matter of running something like:
sudo update-alternatives --install /usr/bin/javac javac \
/usr/lib/jvm/jdk-10.0.2/bin/javac 1010
assuming that one has untarred the OpenJDK tarball for JDK 10 in the above directory (and similarly for javac
) [1].
However, the whole JRE/JDK package contains in excess of 20 binaries, and having a mish-mash of them is a sure recipe for disaster (best case scenario: weird issues and time wasted chasing red herrings).
A much better alternative is to use update-java-alternatives
; however:
- this requires a laborious process of “configuring” the binaries; and
- it needs a
.jinfo
file, which is largely undocumented and no longer a part of the OpenJDK distribution [2]
To overcome both limitations I have created this shell script that takes a JDK distribution, untarred in /usr/lib/jvm
and sets it up as the current JDK.
Usage
Once you have downloaded, for example, OpenJDK 15 and extracted to /usr/lib/jvm
you will have something like the following:
$ ll /usr/lib/jvm
total 12K
lrwxrwxrwx 1 root root 25 Jul 17 2019 default-java -> java-1.11.0-openjdk-amd64
lrwxrwxrwx 1 root root 10 Dec 28 21:57 java-1.11.0-openjdk-amd64 -> jdk-11.0.2
lrwxrwxrwx 1 root root 21 Oct 10 2019 java-1.14.0-openjdk-amd64 -> java-14-openjdk-amd64
drwxr-xr-x 9 root root 4.0K Nov 2 18:47 java-14-openjdk-amd64
drwxrwxr-x 8 marco marco 4.0K Dec 28 21:47 jdk-11.0.2
drwxrwxr-x 8 marco marco 4.0K Dec 28 12:12 jdk-15.0.1
If OpenJDK 14 is your current JDK:
$ java -version
openjdk version "14.0.2" 2020-07-14
OpenJDK Runtime Environment (build 14.0.2+12-Ubuntu-120.04)
OpenJDK 64-Bit Server VM (build 14.0.2+12-Ubuntu-120.04, mixed mode, sharing)
using update-alternatives
will show the two currently available options:
$ update-alternatives --config java
There are 2 choices for the alternative java (providing /usr/bin/java).
Selection Path Priority Status
------------------------------------------------------------
* 1 /usr/lib/jvm/java-14-openjdk-amd64/bin/java 1411 auto mode
2 /usr/lib/jvm/jdk-11.0.2/bin/java 1100 manual mode
Press <enter> to keep the current choice[*], or type selection number:
the priority
column also shows that 14 is the highest (hence, preferred) (the one that would be selected using --auto
).
To add JDK 15 to the list of available alternatives, setting it as the preferred (highest priority) and configuring it to be the currently selected one, simply run:
$ ./update-jdk jdk-15.0.1 1500
$ update-alternatives --config java
There are 3 choices for the alternative java (providing /usr/bin/java).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/lib/jvm/jdk-15.0.1/bin/java 1500 auto mode
1 /usr/lib/jvm/java-14-openjdk-amd64/bin/java 1411 manual mode
2 /usr/lib/jvm/jdk-11.0.2/bin/java 1100 manual mode
3 /usr/lib/jvm/jdk-15.0.1/bin/java 1500 manual mode
Press <enter> to keep the current choice[*], or type selection number:
$ java -version
openjdk version "15.0.1" 2020-10-20
OpenJDK Runtime Environment (build 15.0.1+9-18)
OpenJDK 64-Bit Server VM (build 15.0.1+9-18, mixed mode, sharing)
You will also note that there is a new /usr/lib/jvm/.jdk-15.0.1.jinfo
file, which lists all the binaries that come with the JDK and they all point to the right place [1].
Switching across JDK versions
Once installed for the first time (or even subsequent times) it is best to use the update-java-alternatives
command, with the name of the JDK one wants to activate; given the above folder structure:
$ sudo update-java-alternatives --set jdk-11.0.2
will do the needful:
$ java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
while using update-java-alternatives --auto
will simply pick the highest priority JDK (in the example above, JDK 15).
WARNING using update-alternatives --config java
will naturally work, but only for the java
binary (/usr/bin/java
) while leaving the other binaries pointing to whatever the current JDK is (e.g., javac
may still be pointing to the JDK 14) — this is something that is unlikely to cause happiness.
Notes
[0] Regretfully, a lot of the “tutorials” you find online are written by folks who don’t really understand the topic, and will only get you to change the symlinks for java
and javac
(if you are lucky, javadoc
too, perhaps) – which, again, works most of time; until it doesn’t.
[1] The symlinks are in the /etc/alternatives
directory, and are pointed to from /usr/bin/java
, ‘/usr/bin/javac’, etc.
[2] If it ever was – I have not been able to find it, but a couple were in my /usr/lib/jvm
, although I have no idea how they wound up there; those are what I used as a guide, even though the “official” documentation of update-java-alternatives
(dating back to 2006) is not consistent with the current format.
Leave a Reply