Managing JDKs in MacOS
Tags: java, macos, jdk, java14
Published: 2020-03-25 21:36:56

With the increasing number of JDK builds and the more frequent release cadence, I found it hard to keep track what I had installed in my MacOS and switch between them on the fly.

Even in 2020 my preferred version of Java is 1.8(although I am trying to make use of Java 14 as much as possible), probably because this is the version I am using at my work. But depending on the occasion I find myself experimenting with newer features from later versions, or even from experimental builds:

- JShell from Java 9 onwards
- EpsilonGC 
- The use of `var` since Java 10
- Value types in [Project Valhalla](https://openjdk.java.net/projects/valhalla/) builds
- ZGC (the key feature I want to start making use of Java14)
- etc…

In addition, nowadays on my personal computer I mainly use Java builds from the AdoptOpenJDK project. But there are other builds which I have installed on my MacOS to try out:

- [GraalVM](https://www.graalvm.org/downloads/)
- [Zulu](https://www.azul.com/downloads/zulu-community/?&amp;architecture=x86-64-bit&amp;package=jdk)
- [Coretto](https://aws.amazon.com/corretto/)

Hence I spent some putting together some __bash__ functions that give me a hand managing and switching between those versions on the fly.

For the complete bash script see [here](https://github.com/nikkatsa/nikkatsa-devops/blob/master/dotfiles/.java_profile), but the highlights are:


## List JKDs

```bash
function listJDKs() {
    echo "$($java_home -V 2>&1)"
}
```

### Output
```bash
[:~]$listJDKs
Matching Java Virtual Machines (5):
    14, x86_64:	"AdoptOpenJDK 14"	/Library/Java/JavaVirtualMachines/adoptopenjdk-14.jdk/Contents/Home
    13.0.2, x86_64:	"AdoptOpenJDK 13"	/Library/Java/JavaVirtualMachines/adoptopenjdk-13.jdk/Contents/Home
    1.8.0_222, x86_64:	"AdoptOpenJDK 8"	/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
    1.8.0_212, x86_64:	"GraalVM CE 19.0.0"	/Library/Java/JavaVirtualMachines/graalvm-ce-19.0.0/Contents/Home
    1.8.0_163-zulu-8.28.0.1, x86_64:	"Zulu 8"	/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home
```

## List Different JDK builds

```bash
function listJDKVendors() {
    echo "$($java_home -V 2>&1 | tr ' ' '\0' | tr '\t' ' ' | cut -d ' ' -f2,1)"
}
```
### Output
```bash
[:~]$listJDKVendors
MatchingJavaVirtualMachines(5):
14,x86_64: "AdoptOpenJDK14"
13.0.2,x86_64: "AdoptOpenJDK13"
1.8.0_222,x86_64: "AdoptOpenJDK8"
1.8.0_212,x86_64: "GraalVMCE19.0.0"
1.8.0_163-zulu-8.28.0.1,x86_64: "Zulu8"
```

## Set JDK to a specific version/vendor

```bash
function setJDK() {

    local USAGE="Usage: setJDK [-v \${JDK_VERSION}] [-d \${JDK_DISTRIBUTION}]"

    local OPTIND v d
    while getopts "v:d:" OPTION; do
        case "$OPTION" in
            v)
                local version=$OPTARG
                ;;
            d)
                local dist=$OPTARG
                ;;
            ?)
                echo $USAGE
                return 1
                ;;
        esac
    done

    if [ $# -lt 1 ]; then
        echo $USAGE
        return 1
    fi

    if [ -n "$version" ] && [ "$dist" ]; then
        echo "Setting JAVA to version $version and distribution $dist"
        local versionAndDistNo=$($java_home -V 2>&1 | grep $dist | grep $version | wc -l)
        if [ "$versionAndDistNo" -gt 1 ];then
            echo "Multiple JAVA versions found for arguments -v $version -d $dist . Unable to setJDK"
            listJDKs
            return 1
        else
            export JAVA_HOME=$($java_home -V 2>&1 | grep $dist | grep $version | tr ' ' '\0' | tr '\t' ' ' | cut -d ' ' -f 3)
        fi
    elif [ -n "$dist" ]; then
        echo "Setting JAVA to distribution $dist"
        local distNo=$($java_home -V 2>&1 | grep $dist | wc -l)
        if [ $distNo -gt 1 ];then
            echo "Multiple versions for $dist. Unable to setJDK"
            listJDKs
            return 1
        else
            export JAVA_HOME=$($java_home -V 2>&1 | grep $dist | tr ' ' '\0' | tr '\t' ' ' | cut -d ' ' -f 3)
        fi
    elif [ -n "$version" ]; then
        echo "Setting JAVA to version $version"
        export JAVA_HOME=$($java_home -v $version)
    else
        echo $USAGE
    fi

    echo "JAVA_HOME=${JAVA_HOME}"
    return 0
}
```
### Output
```bash
[:~]setJDK -v 14
Setting JAVA to version 14
JAVA_HOME=/Library/Java/JavaVirtualMachines/adoptopenjdk-14.jdk/Contents/Home
```
> Note that `java_home=/usr/libexec/java_home`