Ubuntu

Switch Default Java Version on Ubuntu / Debian

When multiple Java versions are installed on the same system, only one can be the default. The wrong default breaks builds, crashes application servers, and produces confusing “unsupported class file version” errors. Ubuntu and Debian use the update-alternatives system to manage this, but there are actually four different ways to control which Java version runs, each useful in different scenarios.

Original content from computingforgeeks.com - post 7996

This guide covers all four methods: the system-wide update-alternatives command (interactive and scripted), JAVA_HOME overrides for specific applications, direct path execution for one-off commands, and per-project configuration with build tools. Every example was tested on Ubuntu 24.04 with five OpenJDK versions installed simultaneously (8, 11, 17, 21, and 25).

Current as of March 2026. Verified on Ubuntu 24.04 LTS with OpenJDK 8 (1.8.0_482), 11 (11.0.30), 17 (17.0.18), 21 (21.0.10), and 25 (25.0.2)

Prerequisites

Check Installed Java Versions

Before switching, see what’s registered with the alternatives system:

sudo update-alternatives --list java

With five JDKs installed, the output lists each one:

/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
/usr/lib/jvm/java-11-openjdk-amd64/bin/java
/usr/lib/jvm/java-17-openjdk-amd64/bin/java
/usr/lib/jvm/java-21-openjdk-amd64/bin/java
/usr/lib/jvm/java-25-openjdk-amd64/bin/java

Check the current default:

java -version

The output shows which version is currently active:

openjdk version "25.0.2" 2026-01-20
OpenJDK Runtime Environment (build 25.0.2+10-Ubuntu-124.04)
OpenJDK 64-Bit Server VM (build 25.0.2+10-Ubuntu-124.04, mixed mode, sharing)

Method 1: Interactive Menu (update-alternatives –config)

The interactive method presents a numbered menu and lets you pick:

sudo update-alternatives --config java

The menu shows each version with its priority number. Higher priority means that version wins in auto mode. Type the selection number and press Enter:

There are 5 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                                            Priority   Status
------------------------------------------------------------
* 0            /usr/lib/jvm/java-25-openjdk-amd64/bin/java      2511      auto mode
  1            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   1081      manual mode
  2            /usr/lib/jvm/java-11-openjdk-amd64/bin/java       1111      manual mode
  3            /usr/lib/jvm/java-17-openjdk-amd64/bin/java       1711      manual mode
  4            /usr/lib/jvm/java-21-openjdk-amd64/bin/java       2111      manual mode
  5            /usr/lib/jvm/java-25-openjdk-amd64/bin/java       2511      manual mode

Press  to keep the current choice[*], or type selection number:

Selection 0 (auto mode) always uses the highest-priority version. When you pick a specific number, the system enters manual mode and stays on your choice until you explicitly change it, even if a higher-priority version is installed later.

Do the same for the compiler:

sudo update-alternatives --config javac

Always switch java and javac to the same version. A mismatch (compiling with JDK 21, running with JDK 17) causes bytecode compatibility errors.

Method 2: Non-Interactive Switch (update-alternatives –set)

For scripts, CI pipelines, and automation, use --set to switch without prompts:

Switch to Java 17:

sudo update-alternatives --set java /usr/lib/jvm/java-17-openjdk-amd64/bin/java
sudo update-alternatives --set javac /usr/lib/jvm/java-17-openjdk-amd64/bin/javac

Verify:

java -version

Confirms Java 17 is now the default:

openjdk version "17.0.18" 2026-01-20

Here are the paths for each version on Ubuntu/Debian:

Versionjava Pathjavac PathPriority
Java 8/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java/usr/lib/jvm/java-8-openjdk-amd64/bin/javac1081
Java 11/usr/lib/jvm/java-11-openjdk-amd64/bin/java/usr/lib/jvm/java-11-openjdk-amd64/bin/javac1111
Java 17/usr/lib/jvm/java-17-openjdk-amd64/bin/java/usr/lib/jvm/java-17-openjdk-amd64/bin/javac1711
Java 21/usr/lib/jvm/java-21-openjdk-amd64/bin/java/usr/lib/jvm/java-21-openjdk-amd64/bin/javac2111
Java 25/usr/lib/jvm/java-25-openjdk-amd64/bin/java/usr/lib/jvm/java-25-openjdk-amd64/bin/javac2511

Notice that Java 8’s java binary lives under jre/bin/ while Java 11+ moved it to bin/ directly. The javac binary is always under bin/.

To return to auto mode (highest priority wins):

sudo update-alternatives --auto java
sudo update-alternatives --auto javac

Method 3: JAVA_HOME Override

Some applications (Tomcat, Maven, Gradle, Elasticsearch) read JAVA_HOME instead of using whatever /usr/bin/java points to. You can set this per-session, per-user, or system-wide without touching alternatives at all.

Per-Session (Current Terminal Only)

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
$JAVA_HOME/bin/java -version

Java 17 runs regardless of what /usr/bin/java points to:

openjdk version "17.0.18" 2026-01-20

This only affects the current shell. Close the terminal and it’s gone.

Per-User (Persistent)

Add to ~/.bashrc or ~/.profile:

echo 'export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64' >> ~/.bashrc
source ~/.bashrc

This lets one user run Java 21 while the system default stays on Java 25.

System-Wide (All Users)

Create a profile script that dynamically resolves JAVA_HOME from the current alternatives default:

echo 'export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))' | sudo tee /etc/profile.d/java.sh
source /etc/profile.d/java.sh
echo $JAVA_HOME

Resolves to the current default automatically:

/usr/lib/jvm/java-25-openjdk-amd64

The dynamic approach keeps JAVA_HOME in sync when you switch versions with update-alternatives. For systemd service files where you need a fixed path, set JAVA_HOME explicitly in the unit file:

Environment="JAVA_HOME=/usr/lib/jvm/java-25-openjdk-amd64"

Method 4: Direct Path Execution

Run a specific Java version without changing any defaults. Use the full path:

/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java -version

Runs Java 8 without affecting the system default:

openjdk version "1.8.0_482"

This is useful for testing a specific version or running a legacy application that needs an older JDK while keeping the system default on the latest LTS.

/usr/lib/jvm/java-11-openjdk-amd64/bin/java -jar legacy-app.jar
/usr/lib/jvm/java-25-openjdk-amd64/bin/java -jar modern-app.jar

How Auto Mode and Priorities Work

Each registered alternative has a priority number. In auto mode, the highest priority wins. Ubuntu assigns priorities based on the version number:

VersionPriorityWins in Auto Mode?
Java 81081No
Java 111111No
Java 171711No
Java 212111No
Java 252511Yes (highest)

When you run --config and pick a specific version, the system enters manual mode. It stays on your choice even when you install a new JDK with a higher priority. To go back to auto mode:

sudo update-alternatives --auto java

Check current mode with:

sudo update-alternatives --display java | head -3

The first line tells you whether auto or manual mode is active:

java - auto mode
  link best version is /usr/lib/jvm/java-25-openjdk-amd64/bin/java
  link currently points to /usr/lib/jvm/java-25-openjdk-amd64/bin/java

Switch All JDK Tools at Once

Switching java and javac individually is fine for two tools, but a JDK registers many alternatives: jar, javadoc, jshell, jlink, keytool, and more. To switch all of them at once, use a loop:

TARGET=/usr/lib/jvm/java-21-openjdk-amd64
for tool in java javac jar javadoc javap jcmd jdb jdeps jfr jlink jmod jps jshell jstack jstat keytool; do
  path="$TARGET/bin/$tool"
  [ -f "$path" ] && sudo update-alternatives --set $tool "$path" 2>/dev/null
done
java -version

This ensures all tools point to the same JDK version, avoiding subtle issues where java runs version 25 but jar points to version 17.

Register a Manually Installed JDK

JDKs installed from .deb packages (OpenJDK, Temurin) register themselves automatically. If you installed Oracle JDK from an RPM, a tarball, or a manual download, register it manually:

sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk-25.0.2-oracle-x64/bin/java 1
sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/jdk-25.0.2-oracle-x64/bin/javac 1

The last number is the priority. Set it lower than the system packages (which use 1081+) if you want it as a secondary option, or higher if you want it as the default.

To remove a registered alternative:

sudo update-alternatives --remove java /usr/lib/jvm/jdk-25.0.2-oracle-x64/bin/java

Verify the Configuration

After switching, always verify both the runtime and compiler match:

java -version
javac -version
echo $JAVA_HOME

If java and javac show different versions, switch them both to the same JDK. If JAVA_HOME points to a different version than java -version, an application that reads JAVA_HOME will use a different JDK than one that calls /usr/bin/java directly.

Check where /usr/bin/java actually points through the symlink chain:

readlink -f $(which java)

This resolves all symlinks and shows the final binary path.

Which Method to Use

ScenarioMethod
Change the system default permanentlyupdate-alternatives --set or --config
Run a specific app with a different JDKSet JAVA_HOME in the app’s systemd unit or wrapper script
Quick test with an older versionUse the direct path: /usr/lib/jvm/java-11-openjdk-amd64/bin/java
CI/CD pipeline version pinningupdate-alternatives --set in the pipeline script
One user needs a different versionSet JAVA_HOME in ~/.bashrc
Multiple apps, each needing different JDKsSet JAVA_HOME per systemd unit file, leave system default on latest

For installing Java on your system, see our guides for JDK 25 on Ubuntu, JDK 25 on Debian, or JDK 25 on Rocky Linux / AlmaLinux.

Related Articles

Debian Install OpenResty Web Platform on Ubuntu / Debian Debian Install and Configure SSH Server on Ubuntu 24.04 / Debian 13 Databases Install PostgreSQL 11 on Ubuntu 22.04|20.04|18.04|16.04 Debian Install Python 3.9 on Debian 11 / Debian 10

1 thought on “Switch Default Java Version on Ubuntu / Debian”

Leave a Comment

Press ESC to close