Easily Switching JDKs
Monday, August 26, 2019 |Development environments can get fairly complex, and making sure you’re using the right version of some library or another can be annoying on the best of days. I have a situation like that where my "day job" requires (still, and hopefully not for much longer) JDK 8, but my side projects, learning efforts, etc. can use a more modern version.
Years ago, Charles Nutter shared a shell script he uses to switch JDKs. I’ve been happily using it, but I’ve made some minor tweaks, so I thought I’d share my version here in case it helps someone (and make it easier for me to find in the future ;).
UPDATE: It seems the original author is Nick Sieger. Thanks to you as well, Nick, for a great little utility!
The two primary changes in my script versus Charles' is that I try to set JDKS_ROOT if it’s not already set, and I try to filter out "false" JDK entries (where the Ubuntu packages, for example, seem to like to create symlinks). I have not tested these changes to make sure I haven’t broken MacOS support, however, so if you’re on a Mac and this doesn’t work correctly, please let me know. :)
Without further ado:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/bin/bash
#
# Provides a function that allows you to choose a JDK. Just set the environment
# variable JDKS_ROOT to the directory containing multiple versions of the JDK
# and the function will prompt you to select one. JAVA_HOME and PATH will be cleaned
# up and set appropriately.
# Usage:
# Include in .profile or .bashrc or source at login to get 'pickjdk' command.
# 'pickjdk' alone to bring up a menu of installed JDKs on OS X. Select one.
# 'pickjdk <jdk number>' to immediately switch to one of those JDKs.
_checkos()
{
if [ $(uname -s) = $1 ]; then
return 0
else
return 1
fi
}
if [ -z "$JDKS_ROOT" ] ; then
if _checkos Linux ; then
JDKS_ROOT=/usr/lib/jvm
elif _checkos Darwin ; then
JDKS_ROOT=/Library/Java/JavaVirtualMachines
fi
fi
pickjdk()
{
if [ -z "$JDKS_ROOT" ]; then
return 1
fi
declare -a JDKS
local n=1 jdk total_jdks choice=0 currjdk=$JAVA_HOME explicit_jdk
for jdk in $JDKS_ROOT/[0-9a-z]*; do
if [ ! -L $jdk -a -d $jdk -a -e $jdk/bin ]; then
JDKNAMES[$n]="$(basename $jdk)"
if _checkos Darwin ; then
jdk=$jdk/Contents/Home
fi
if [ -z "$1" ]; then
echo -n " $n) ${JDKNAMES[$n]}"
if [ $jdk = "$currjdk" ]; then
echo " < CURRENT"
else
echo
fi
fi
JDKS[$n]=$jdk
total_jdks=$n
n=$[ $n + 1 ]
fi
done
if [ -z "$1" ]; then
echo " $n) None"
fi
JDKS[$n]=None
total_jdks=$n
if [ $total_jdks -gt 1 ]; then
if [ -z "$1" ]; then
while [ -z "${JDKS[$choice]}" ]; do
echo -n "Choose one of the above [1-$total_jdks]: "
read choice
done
else
choice=$1
fi
fi
if [ -z "$currjdk" ]; then
currjdk=$(dirname $(dirname $(type -path java)))
fi
if [ ${JDKS[$choice]} != None ]; then
export JAVA_HOME=${JDKS[$choice]}
else
unset JAVA_HOME
fi
explicit_jdk=
for jdk in ${JDKS[*]}; do
if [ "$currjdk" = "$jdk" ]; then
explicit_jdk=$jdk
break
fi
done
if [ "$explicit_jdk" ]; then
if [ -z "$JAVA_HOME" ]; then
PATH=$(echo $PATH | sed "s|$explicit_jdk/bin:*||g")
else
PATH=$(echo $PATH | sed "s|$explicit_jdk|$JAVA_HOME|g")
fi
elif [ "$JAVA_HOME" ]; then
PATH="$JAVA_HOME/bin:$PATH"
fi
echo "New JDK: ${JDKNAMES[$choice]}"
hash -r
}
To use this, add the following to your Bash profile:
1
source /path/to/pickjdk.sh
Restart your shell (or source the file directly), and you can do this:
1
2
3
4
5
$ pickjdk
1) java-11-openjdk-amd64 < CURRENT
2) oracle-java8-jdk-amd64
3) None
Choose one of the above [1-3]:
Make your selection, and you’re all set. It’s awesome.