Skip to content

Instantly share code, notes, and snippets.

@tofi86
Last active January 29, 2018 23:19
Show Gist options
  • Save tofi86/3d5973f8cb259f07207451d051a52ae1 to your computer and use it in GitHub Desktop.
Save tofi86/3d5973f8cb259f07207451d051a52ae1 to your computer and use it in GitHub Desktop.
Find a suitable Java Virtual Machine on Mac OS X which matches a min/max version requirement
#!/bin/bash
function get_java_version_from_cmd() {
# second sed command strips " and -ea from the version string
echo $("$1" -version 2>&1 | awk '/version/{print $NF}' | sed -E 's/"//g;s/-ea//g')
}
function get_comparable_java_version() {
# cleaning: 1) remove leading '1.'; 2) remove 'a-Z' and '-*+' (e.g. '-ea'); 3) replace '_' with '.'
local cleaned=$(echo "$1" | sed -E 's/^1\.//g;s/[a-zA-Z+*\-]//g;s/_/./g')
# splitting at '.' into an array
local arr=( ${cleaned//./ } )
# echo a string with left padded version numbers
echo "$(printf '%02s' ${arr[0]})$(printf '%03s' ${arr[1]})$(printf '%03s' ${arr[2]})"
}
min=1.8
minC=$(get_comparable_java_version $min)
max=9
maxC=$(get_comparable_java_version $max)
# default Apple JRE plugin path
apple_jre_plugin="/Library/Java/Home/bin/java"
apple_jre_version=$(get_java_version_from_cmd "${apple_jre_plugin}")
# default Oracle JRE plugin path
oracle_jre_plugin="/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java"
oracle_jre_version=$(get_java_version_from_cmd "${oracle_jre_plugin}")
########################################
# find installed JavaVirtualMachines (JDK + JRE)
############################################
allJVMs=()
# read JDK's from '/usr/libexec/java_home -V' command
while read line; do
version=$(echo $line | awk -F $',' '{print $1;}')
path=$(echo $line | awk -F $'" ' '{print $2;}')
path+="/bin/java"
allJVMs+=("$version:$path")
done < <(/usr/libexec/java_home -V 2>&1 | grep '^[[:space:]]')
# unset while loop variables
unset version path
# add Apple JRE if available
if [ -x "${apple_jre_plugin}" ] ; then
allJVMs+=("$apple_jre_version:$apple_jre_plugin")
fi
# add Oracle JRE if available
if [ -x "${oracle_jre_plugin}" ] ; then
allJVMs+=("$oracle_jre_version:$oracle_jre_plugin")
fi
# debug output
echo ""
echo "Found:"
for i in "${allJVMs[@]}"
do
echo $i
done
# determine JVMs matching the min/max version requirement
############################################
matchingJVMs=()
for i in "${allJVMs[@]}"
do
# split JVM string at ':' delimiter to retain spaces in $path substring
IFS=: arr=($i) ; unset IFS
# [0] JVM version number
ver=${arr[0]}
# comparable JVM version number
comp=$(get_comparable_java_version $ver)
# [1] JVM path
path="${arr[1]}"
# construct string item for adding to the "matchingJVMs" array
item="$comp:$ver:$path"
# pre-requisite: current version number needs to be greater than min version number
if [ "$comp" -ge "$minC" ] ; then
# perform max version checks if max version requirement is present
if [ ! -z ${max} ] ; then
# max version requirement ends with '*' modifier
if [[ ${max} == *\* ]] ; then
# use the '*' modifier from the max version string as wildcard for a 'starts with' comparison
# and check whether the current version number starts with the max version wildcard string
if [[ ${ver} == ${max} ]]; then
matchingJVMs+=("$item")
# or whether the current comparable version is lower than the comparable max version
elif [ "$comp" -le "$maxC" ] ; then
matchingJVMs+=("$item")
fi
# max version requirement ends with '+' modifier -> always add this version if it's greater than $min
# because a max requirement with + modifier doesn't make sense
elif [[ ${max} == *+ ]] ; then
matchingJVMs+=("$item")
# matches 6 zeros at the end of the max version string (e.g. for 1.8, 9)
# -> then the max version string should be treated like with a '*' modifier at the end
#elif [[ ${maxC} =~ ^[0-9]{2}0{6}$ ]] && [ "$comp" -le $(( ${maxC#0} + 999 )) ] ; then
# matchingJVMs+=("$item")
# matches 3 zeros at the end of the max version string (e.g. for 9.1, 10.3)
# -> then the max version string should be treated like with a '*' modifier at the end
#elif [[ ${maxC} =~ ^[0-9]{5}0{3}$ ]] && [ "$comp" -le "${maxC}" ] ; then
# matchingJVMs+=("$item")
# matches standard requirements without modifier
elif [ "$comp" -le "$maxC" ]; then
matchingJVMs+=("$item")
fi
# no max version requirement -> add current version to matching list
else
matchingJVMs+=("$item")
fi
fi
done
# unset for loop variables
unset arr ver comp path item
# debug output
echo ""
echo "Matching:"
for i in "${matchingJVMs[@]}"
do
echo $i
done
# sort the matching JavaVirtualMachines by version number
############################################
# https://stackoverflow.com/a/11789688/1128689
IFS=$'\n' matchingJVMs=($(sort -nr <<<"${matchingJVMs[*]}"))
unset IFS
# debug output
echo ""
echo "Sorted:"
for i in "${matchingJVMs[@]}"
do
echo $i
done
# get the highest matching JVM
############################################
JAVACMD=
JAVACMD_version=
for ((i = 0; i < ${#matchingJVMs[@]}; i++));
do
# split JVM string at ':' delimiter to retain spaces in $path substring
IFS=: arr=(${matchingJVMs[$i]}) ; unset IFS
# [0] comparable JVM version number
comp=${arr[0]}
# [1] JVM version number
ver=${arr[1]}
# [2] JVM path
path="${arr[2]}"
# use current value as JAVACMD if it's executable
if [ -x "$path" ] ; then
JAVACMD="$path"
JAVACMD_version=$comp
break
fi
done
# unset for loop variables
unset arr comp ver path
# debug output
echo ""
echo "Highest:"
echo $JAVACMD
echo $JAVACMD_version
if [ -x "$JAVACMD" ] ; then
echo $("${JAVACMD}" -version)
fi
@tofi86
Copy link
Author

tofi86 commented Jan 29, 2018

Output for

min=1.7
max=1.8*

on my current system:

Found:
9.0.1:/Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/java
9:/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/bin/java
1.8.0_144:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java
1.7.0_79:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/bin/java
9.0.1:/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java

Matching:
08000144:1.8.0_144:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java
07000079:1.7.0_79:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/bin/java


Sorted:
08000144:1.8.0_144:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java
07000079:1.7.0_79:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/bin/java

Highest:
/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java
08000144
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

picks Java 1.8.0_144 because max=1.8 selects all Java 1.8 versions.

@tofi86
Copy link
Author

tofi86 commented Jan 29, 2018

Output for

min=1.6
max=1.7.0_41

on my current system:

Found:
9.0.1:/Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/java

9:/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/bin/java
1.8.0_144:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java
1.7.0_79:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/bin/java
9.0.1:/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java

Matching:

Sorted:

Highest:

doesn't match no JVM installed on my system cause I don't have Java 6 and 1.7.0_41 is lower than my installed JDK 1.7.0_79

@tofi86
Copy link
Author

tofi86 commented Jan 29, 2018

Output for

min=9
max=

on my current system:

Found:
9.0.1:/Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/java
9:/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/bin/java
1.8.0_144:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java
1.7.0_79:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/bin/java
9.0.1:/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java

Matching:
09000001:9.0.1:/Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/java
09000000:9:/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/bin/java
09000001:9.0.1:/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java

Sorted:
09000001:9.0.1:/Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/java
09000001:9.0.1:/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java
09000000:9:/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/bin/java

Highest:
/Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/java
09000001
java version "9.0.1"
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)

matches all the Java 9 versions because no max version is required

@tofi86
Copy link
Author

tofi86 commented Jan 29, 2018

Output for

min=1.7.0_79
max=1.8.0_144

on my current system:

Found:
9.0.1:/Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/java
9:/Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home/bin/java
1.8.0_144:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java
1.7.0_79:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/bin/java
9.0.1:/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java

Matching:
08000144:1.8.0_144:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java
07000079:1.7.0_79:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/bin/java


Sorted:
08000144:1.8.0_144:/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java
07000079:1.7.0_79:/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/Home/bin/java

Highest:
/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java
08000144
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

matches my JDK 7 and JDK 8.

Note that max is interpreted as lower or equal than $max!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment