How to manage multiple Java versions on Windows PC?

In this post, we'll discuss how to quickly install and switch between different Java versions on a Windows machine.

When Oracle decided to go with the six-month release cycle for new Java versions, many developers started to work with more than one Java version at a time.  It is relatively easy to switch between different versions on a Mac or Linux-based system, thanks to utilities like Jabba and jEnv; But on Windows, this is not as straightforward.

Jabba can install multiple Java versions on a Windows PC machine, but it does not set the corresponding persistentJAVA_HOME or Path variables for the current user. jEnv, on the other hand, does not work at all on Windows PC machine and can only be used for Mac or Linux based setups.

In the following sections, we will see how we can use Jabba (for installation of various versions) and a custom batch script to switch between these (Jabba installed) versions to solve the issues mentioned earlier.

Installing Jabba

Installing Jabba is straightforward. All you need to do is run the following command from PowerShell as an administrator.

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-Expression (
  Invoke-WebRequest https://github.com/shyiko/jabba/raw/master/install.ps1 -UseBasicParsing
).Content

Once Jabba is installed, we can use the same to install different Java versions as per the requirement. You can look into the official documentation for the support. In its simplest version, the following commands will install openjdk15 and adoptOpenJdk8 on the machine:

# fetch and install openjdk versions available in the remote repo
jabba ls-remote | grep "openjdk"
jabba install openjdk@1.15.0

# fetch and install adoptOpenJdk versions available in the remote repo
jabba ls-remote | grep "adopt"
jabba install adopt@1.8.0-275

The problem with Jabba is that the Path and JAVA_HOME variables set via the use command last only the current session. If we need to persist the value of these, we need to manually put these in the environment variables. But when you have more than a few versions installed, manually updating the environment variables to point to the required version quickly becomes a challenge.

Batch Script

I drafted a list of requirements that the script should support. Primarily it should:

  1. Update the JAVA_HOME and Path environment variables for the current user.
  2. It should not update the System environment variables.
  3. If the Path environment variable already contains a JDK entry, it should update the same instead of adding a new entry, which might corrupt the setup.

Before we look at the batch-script itself, I want to highlight the following assumptions:

  1. All the Java versions are setup using Jabba.
  2. The Java versions are installed on the default location, which is  %USERPROFILE%\.jabba\jdk
  3. The Path variable, if not set based on the JVM_HOME variable (i.e., %JAVA_HOME%/bin) and was set manually, will contain the .jabba\jdk in it.
# a utility script to set java environment variables
# as downloaded by jabba (https://github.com/shyiko/jabba)
# on a windows10 PC machine

# developed by gaurs (https://github.com/gaurs)
# updated on: 07-Feb-2021
# posted on jvmaware blog (https://jvmaware.com/blog/multiple-java-versions/)

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS

SET COUNT=1
SET UPDATED_PATH=""
SET CURR_PATH=""

IF "%~1"=="ls" (GOTO LS)
IF "%~1"=="use" (GOTO USE) ELSE (GOTO NONE)

:LS
    SET FROM=%USERPROFILE%\.jabba\jdk
    CD %FROM%
    FOR /F "DELIMS=" %%D in ('DIR /A:D /B') DO (
        ECHO %%~D
    )
EXIT /B 0

:USE
    SET FROM=%USERPROFILE%\.jabba\jdk
    CD %FROM%
    
    FOR /F "DELIMS=" %%D in ('DIR /A:D /B') DO (
        SET name!COUNT!=%%~D
        SET path!COUNT!=%%~FD
        SET /a COUNT=!COUNT!+1
    )
    
    SET OPTION=%~2
    SET NAME=!name%OPTION%!
    SET LOCATION=!path%OPTION%!
    ECHO selected option: %NAME% from locaton: %LOCATION%
    
    GOTO SETPATHS
EXIT /B 0


:SETPATHS
    ECHO setting the paths for current user only
    SETX JAVA_HOME %LOCATION%
    
    SET Key="HKCU\Environment"
    FOR /F "USEBACKQ TOKENS=2*" %%A IN (`REG QUERY %Key% /v PATH`) DO SET CURR_PATH=%%B
    
    SET List=%CURR_PATH%
    GOTO :PROCESS_LIST
EXIT /B 0

:PROCESS_LIST
    FOR /F "TOKENS=1* DELIMS=;" %%a IN ("!List!") DO ( 
        IF "%%a" NEQ "" ( 
            ECHO %%a | findstr /C:".jabba\jdk">null
            SET CODE=%errorlevel%
            IF "%CODE%"=="1" (
                SET UPDATED_PATH=%UPDATED_PATH%;%%JAVA_HOME%%\bin
                SET CODE=0
            )ELSE (
                IF "%UPDATED_PATH%"=="""" (
                    SET UPDATED_PATH=%%a
                )ELSE (
                    SET UPDATED_PATH=%UPDATED_PATH%;%%a
                )
            )
        )
        IF "%%b" NEQ "" (
            SET List=%%b
            GOTO :PROCESS_LIST
        )
    )
    GOTO UPDATE_PATH_VALUE
EXIT /B 0

:UPDATE_PATH_VALUE
    ECHO Setting path to: %UPDATED_PATH%
    SETX PATH "%UPDATED_PATH%"
    ECHO JAVA_HOME and PATH updated to the selected values for current user
    EXIT /B 0
:NONE
    ECHO please enter valid value
EXIT /B 0

The script works by listing the currently installed java versions inside the %USERPROFILE%\.jabba\jdk location, and then the user can select any one of those.

A sample execution of the same looks something like this:

> jdkMan.bat ls
adopt@1.8.0-275
openjdk@1.15.0-1

> jdkMan.bat use 1
selected option: adopt@1.8.0-275 from locaton: C:\Users\gaurs\.jabba\jdk\adopt@1.8.0-275
setting the paths for current user only

SUCCESS: Specified value was saved.
Setting path to: %USERPROFILE%\AppData\Local\Microsoft\WindowsApps;%JAVA_HOME%\bin;...

SUCCESS: Specified value was saved.
JAVA_HOME and PATH updated to the selected values for current user

You can check the environment variables for the current user and those should reflect the changes as listed below:

Updated Environment Variables

As always, I hope you find this article and the batch script helpful. Please drop me an email if you have any suggestions or queries. I’ll try to answer your questions at the earliest.

That’s it for now. Keep learning, Keep Coding.

Be notified of new posts. Subscribe to the RSS feed.