3

Background

I work mostly in Java and Scala on my job, but a lot of our legacy code has not yet been updated to the most recent JDK. Thus, we have to have JDK versions 5, 6, 7, and 8 installed on our development machines. Until recently, I had been using Arch Linux, but I just switched to OpenSuse Tumbleweed. The method I used to install the JDK versions was to download the RPM installer scripts from the Oracle website and install them beginning with 1.5 and working my way up to 1.8 so that the /usr/java/latest symbolic link would already be pointing to the correct version.

Problem

After reinstalling the aforementioned JDK versions, I attempted to point to these installations in IntelliJ IDEA. But it complained with the error "The selected directory is not a valid home for JDK". I have found a lot of resources online concerning this issue and ones like it, but none of those solutions helped in my case. Furthermore, the symbolic links in /usr/bin for the sundry Java executables were pointing to a conflagration of /etc/alternatives directives.

Jonathan E. Landrum
  • 2,748
  • 4
  • 30
  • 46

3 Answers3

7

Solution

Apparently, the RPM scripts that Oracle releases tend to break any previous JDK versions you have installed by way of removing key JAR files from those older installations, such as tools.jar and rt.jar. This renders the formerly functioning JDK useless for developers.

My first response was to rename the installation directory prior to running the second installer script. But doing that made RPM complain about already having a version of the JDK installed when running the second script. So the hack of the hack is to install one version, rename that directory, then "remove" that version with RPM (even though it will complain about not being able to find any of the respective files associated with it). Then you are free to install the second version, repeating the previous steps for each one until you get to the latest version you wish to install.

TL;DR

Here are the steps to get multiple working JDK versions on the same machine:

1. Install the first version of the JDK using the installer script:

:~# chmod a+x jdk-1_5_0_22-linux-amd64-rpm.bin
:~# ./jdk-1_5_0_22-linux-amd64-rpm.bin -x
:~# rpm -ivh --replacepkgs jdk-1_5_0_22-linux-amd64.rpm

2. Rename the install directory:

:~# mv /usr/java/jdk1.5.0_22 /usr/java/jdk1.5.0_22-bak

3. Use RPM to uninstall that version of the JDK:

:~# rpm -e jdk-2000:1.5.0_22-fcs.x86_64

4. Rinse and repeat until all versions are installed

5. Remove the -bak from the end of the directory names

:~# mv /usr/java/jdk1.5.0_22-bak /usr/java/jdk1.5.0_22

6. Change the /usr/java symlinks to the correct target:

:~# ls -la /usr/java
default -> java7
java5 -> jdk1.5.0_22
java6 -> jdk1.6.0_45
java7 -> jdk1.7.0_80
java8 -> jdk1.8.0_101
jdk1.5.0_22
jdk1.6.0_45
jdk1.7.0_80
jdk1.8.0_101
latest -> java8

7. Change the /usr/bin symlinks to the correct target:

:~# ls -la /usr/bin/ja*
jar -> /usr/java/default/bin/jar
java -> /usr/java/default/bin/java
javac -> /usr/java/default/bin/javac
javadoc -> /usr/java/default/bin/javadoc
javah -> /usr/java/default/bin/javah
javaws -> /usr/java/default/bin/javaws
Jonathan E. Landrum
  • 2,748
  • 4
  • 30
  • 46
3

On ubuntu/linux you can switch java version using

update-alternatives --config java

But before, you need install the version.

You can use this script (./install-java.sh) to install multiple JVMs

#!/bin/sh
(
lookforJdks=$PWD
echo "Directory: $lookforJdks"
jdks=`test -e ./javac || find $lookforJdks -type d -iname '*jdk1.*' 2> /dev/null`
#set -e
echo 'which jdk do you want to choose? looking for jdks. This might take a while'
echo "$jdks" | awk '{printf("%5d : %s\n", NR,$0)}'
read choose
test -e ./javac || cd `echo "$jdks" | tr '\n' ',' | cut -d',' -f $choose`/bin
for e in appletviewer extcheck idlj jar jarsigner java javac javadoc javah javap jconsole \
 jdb jhat jinfo jmap jps jrunscript jsadebugd jstack jstat jstatd native2ascii rmic \
 schemagen serialver wsgen wsimport xjc jvisualvm jmc; do sudo update-alternatives \
 --install /usr/bin/$e $e $(readlink -f ./$e) 100; done
)

echo "RUN update-alternatives --config java"

Put this script in folder where has unpacked the JVM(s), an run:

/opt/install-java.sh

Next use: update-alternatives --config java

  • 2
    That still doesn't solve the issue with Oracle's installer packages breaking previous versions. *It also doesn't actually solve the problem asked.* This solution just concerns which version `/usr/bin/java` references. I specify which JDK to use directly from within my IDE, so the symbolic link `/usr/bin/java` is irrelevant. The problem is the old JDKs are rendered useless after installing a newer one. Hence the clusterfuck solution I posted. – Jonathan E. Landrum Jan 18 '17 at 16:43
  • 1
    `update-alternatives` will not update `JAVA_HOME` or `JRE_HOME` and there is more than one binary in `jre/bin` to update in `PATH`. – Pierre Thibault Jun 05 '19 at 18:53
1

Alternatives are good points to manage your jdks, but if you are looking to an easy way to manage multiple versions of JDK, Maven, Gradle, ... you can use SDKMAN. for example in order to install JDK just enter
sdk install java in your terminal.
and to switch to other version just enter:
sdk default java version

Amir
  • 1,123
  • 8
  • 15
  • 1
    `update-alternatives` is a *terrible* way to handle working with multiple JDKs. You're suggesting I have to run `update-alternatives` every time I switch projects? – Jonathan E. Landrum Oct 17 '19 at 13:15
  • 1
    The SDKMAN project looks interesting, but again, the problem isn't with which version my command prompt thinks is the default Java; the problem is with having multiple *development* versions installed. This isn't about running Java, it's about developing in Java. – Jonathan E. Landrum Oct 17 '19 at 13:22