# 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 persistent JAVA_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


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
# 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
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
openjdk@1.15.0-1

> jdkMan.bat use 1
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:

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.

How To

### Sumit Gaur

A passionate java developer and open source advocate, who understands the value of continuous learning and sharing knowledge.

Members Public

## Lambda Expressions and Exception Handling

This short article will explore a few options to handle checked and unchecked exceptions in lambda expressions.

Members Public

## Streams and Iterables

In this short article, we'll explore various StreamSupport methods that allow us to wrap an Iterable instance as a stream of elements.

Members Public

## Checked Collection - stronger type safety

CheckedCollection helps to enforce strong type safety when mixing generic and non-generic code.