loading...

Managing JDKs in MacOS

nikos_katsanos profile image Nikos Katsanos ・3 min read

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 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:

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, but the highlights are:

List JKDs

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

Output

[:~]$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

function listJDKVendors() {
    echo "$($java_home -V 2>&1 | tr ' ' '\0' | tr '\t' ' ' | cut -d ' ' -f2,1)"
}

Output

[:~]$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

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

[:~]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

Posted on May 23 by:

Discussion

markdown guide
 

Hi Nikos,

nice article. I had to same, needing to change my JDK for multiple projects with a new developed and a legacy code base. For me i found sdkman very helpful (sdkman.io/).
It dose the same job as your script + it allows you to download additional JDKs if needed. Also tools like gradle can be managed with it and maintained in multiple versions.

 

Hey Philip, Thank you for the suggestion. Didn't know about that, but it looks pretty cool and promising. Will give it a go. I definitely prefer something that is supported by many people :)

 

Hi Nikos,

I encountered this problem using an SDK for iOS application obfuscation.
I used jenv and it works pretty well.

 

Hello Rèmi, thank you for suggesting. Seems like managing JDKs in a Mac/Dev machine is a general concern. jevn looks promising as well. Pretty sure this and http:// sdkman.io as suggested above will be much better than my hacky scripts :)

 

I explained how I made it in that Post :

It is basically :

brew install jenv
echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(jenv init -)"' >> ~/.bash_profile
source ~/.bash_profile