Debian 13 ships OpenJDK 21 and 25 and nothing older, so asking apt for openjdk-17-jdk on it ends with “Unable to locate package”.
Debian 12 is the mirror image, because its archive stops at OpenJDK 17. So how you install Java on Debian depends on two things, the release you run and the Java version your application needs.
Below, you install OpenJDK 25 and 21 from the Debian repository, any other LTS release from Eclipse Temurin, and Oracle JDK from its .deb package. It then covers switching between versions, setting JAVA_HOME, and what each JDK costs on disk.
Tested October 2026 with OpenJDK 25.0.4.1 on Debian 13 and Debian 12.
Install Java on Debian by release
Debian packages two LTS releases on trixie and only one on bookworm, and every other Java version is installed from a third-party repository.
| Java version | Debian 13 (trixie) | Debian 12 (bookworm) |
|---|---|---|
| 25 (current LTS) | openjdk-25-jdk | Temurin or Oracle JDK |
| 21 (previous LTS) | openjdk-21-jdk (default-jdk) | Temurin |
| 17 | Temurin | openjdk-17-jdk (default-jdk) |
| 11 or 8 | Temurin | Temurin |
Before you pick a row, check what your own mirror offers with apt-cache, which lists every candidate version and the suite it comes from.
apt-cache madison openjdk-17-jdk openjdk-21-jdk openjdk-25-jdk default-jdk
On our Debian 13 server only 21 and 25 came back, and default-jdk points at 21.
openjdk-21-jdk | 21.0.12.1+1-1~deb13u1 | mirror+file:/etc/apt/mirrors/debian.list trixie/main amd64 Packages
openjdk-21-jdk | 21.0.12.1+1-1~deb13u1 | mirror+file:/etc/apt/mirrors/debian-security.list trixie-security/main amd64 Packages
openjdk-25-jdk | 25.0.4.1+1-1~deb13u1 | mirror+file:/etc/apt/mirrors/debian-security.list trixie-security/main amd64 Packages
openjdk-25-jdk | 25.0.3+9-2~deb13u1 | mirror+file:/etc/apt/mirrors/debian.list trixie/main amd64 Packages
default-jdk | 2:1.21-76 | mirror+file:/etc/apt/mirrors/debian.list trixie/main amd64 Packages
Debian 12 returned a single JDK, version 17, and its bookworm-backports suite carries no newer OpenJDK either.
openjdk-17-jdk | 17.0.20.1+1-1~deb12u1 | mirror+file:/etc/apt/mirrors/debian-security.list bookworm-security/main amd64 Packages
openjdk-17-jdk | 17.0.19+10-1~deb12u2 | mirror+file:/etc/apt/mirrors/debian.list bookworm/main amd64 Packages
default-jdk | 2:1.17-74 | mirror+file:/etc/apt/mirrors/debian.list bookworm/main amd64 Packages
Before you upgrade Debian 12 to Debian 13, move Java 17 applications to Temurin 17 or to OpenJDK 21 first. Debian 13 has no openjdk-17 package to upgrade to.
Step 1: Install OpenJDK 25 on Debian 13
OpenJDK 25 is in the main Debian 13 archive, so you need no extra repository and can install it right after you refresh the package index.
sudo apt update
On a server, install the headless JDK, which still gives you the compiler and every command-line tool and only leaves out the AWT and Swing libraries:
sudo apt install -y openjdk-25-jdk-headless
apt fetched 149 MB and used 364 MB of disk on our test box. The full openjdk-25-jdk package is meant for desktops. On a box with only the headless JDK, it pulled in 131 more packages, 111 of them X11, GTK, font, image and audio libraries, which added another 445 MB.
To confirm the install, check the runtime and the compiler:
java -version
javac -version
Both report the same build, and the vendor string ends in Debian:
openjdk version "25.0.4.1" 2026-08-18
OpenJDK Runtime Environment (build 25.0.4.1+1-1-deb13u1-Debian)
OpenJDK 64-Bit Server VM (build 25.0.4.1+1-1-deb13u1-Debian, mixed mode, sharing)
javac 25.0.4.1
Step 2: Add OpenJDK 21
Several JDKs can live side by side under /usr/lib/jvm, so if an application has not moved to 25 yet, install 21 next to it.
sudo apt install -y openjdk-21-jdk-headless
OpenJDK 21 took 17 seconds and another 300 MB, and your default java did not change, because each JDK is ranked by version:
update-alternatives --display java
Version 25 carries priority 2511 against 2111 for version 21, so auto mode keeps 25:
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
link java is /usr/bin/java
slave java.1.gz is /usr/share/man/man1/java.1.gz
/usr/lib/jvm/java-21-openjdk-amd64/bin/java - priority 2111
slave java.1.gz: /usr/lib/jvm/java-21-openjdk-amd64/man/man1/java.1.gz
/usr/lib/jvm/java-25-openjdk-amd64/bin/java - priority 2511
slave java.1.gz: /usr/lib/jvm/java-25-openjdk-amd64/man/man1/java.1.gz
Auto mode always picks the highest priority, so Step 6 shows how to make 21 the default when an application needs it.
Step 3: Install Java on Debian 12
Debian 12 packages Java 17 itself, and anything newer comes from the Eclipse Temurin repository, which Adoptium builds from the same OpenJDK source.
OpenJDK 17 from the Debian archive
Refresh the package index, then install the headless JDK that bookworm ships as its default-jdk:
sudo apt update
sudo apt install -y openjdk-17-jdk-headless
OpenJDK 17 downloaded 122 MB on our Debian 12 server and used 289 MB. Check it by its full path, which works even when another JDK is the default:
/usr/lib/jvm/java-17-openjdk-amd64/bin/java -version
Its build string ends in deb12u1-Debian.
openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment (build 17.0.20.1+1-1-deb12u1-Debian)
OpenJDK 64-Bit Server VM (build 17.0.20.1+1-1-deb12u1-Debian, mixed mode, sharing)
Java 21 or 25 from Temurin
Adoptium publishes the Temurin repository for both bookworm and trixie. If you skipped the 17 install above, run sudo apt update first, then install wget and gpg, which fetch the signing key and convert it to the binary format apt expects:
sudo apt install -y wget gpg
Save the key in its own keyring. The Adoptium install page puts it in trusted.gpg.d, where apt trusts it for every repository. A signed-by keyring limits it to this one:
sudo install -d -m 0755 /etc/apt/keyrings
wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor | sudo tee /etc/apt/keyrings/adoptium.gpg > /dev/null
Add the repository. The codename is read from /etc/os-release, so the same line works on Debian 13:
echo "deb [signed-by=/etc/apt/keyrings/adoptium.gpg] https://packages.adoptium.net/artifactory/deb $(. /etc/os-release; echo $VERSION_CODENAME) main" | sudo tee /etc/apt/sources.list.d/adoptium.list
tee echoes the line back, and on Debian 12 it ends in bookworm main.
Once the line is in place, refresh the index and list the JDKs on offer:
sudo apt update
apt-cache search --names-only "^temurin-[0-9]+-jdk$" | sort -V
Every LTS release since 8 is there, plus the short-lived feature releases up to 27:
temurin-8-jdk - Eclipse Temurin 8 JDK
temurin-11-jdk - Eclipse Temurin 11 JDK
temurin-17-jdk - Eclipse Temurin 17 JDK
temurin-20-jdk - Eclipse Temurin 20 JDK
temurin-21-jdk - Eclipse Temurin 21 JDK
temurin-22-jdk - Eclipse Temurin 22 JDK
temurin-23-jdk - Eclipse Temurin 23 JDK
temurin-24-jdk - Eclipse Temurin 24 JDK
temurin-25-jdk - Eclipse Temurin 25 JDK
temurin-26-jdk - Eclipse Temurin 26 JDK
temurin-27-jdk - Eclipse Temurin 27 JDK
To install Java 25, run:
sudo apt install -y temurin-25-jdk
Temurin 25 downloaded 115 MB and used 331 MB. Temurin ships no headless variant, so it also pulls in a few X11 client libraries, and its version string names Temurin and marks the build as LTS.
java -version
Our Debian 12 server printed:
openjdk version "25.0.4.1" 2026-08-18 LTS
OpenJDK Runtime Environment Temurin-25.0.4.1+1 (build 25.0.4.1+1-LTS)
OpenJDK 64-Bit Server VM Temurin-25.0.4.1+1 (build 25.0.4.1+1-LTS, mixed mode, sharing)
For Java 21, use the same command with temurin-21-jdk. Temurin registers the same priorities as the Debian packages (2111 for 21, 2511 for 25), so the newest JDK wins auto mode here too.
Step 4: Java 17 on Debian 13
Java 17 and 11 are installed from the same Temurin repository on Debian 13, so if you skipped Step 3, run its Temurin commands first, from sudo apt install -y wget gpg through sudo apt update.
Error: “E: Unable to locate package openjdk-17-jdk”
Debian 13 prints this when you ask for the Debian 12 package name, because the trixie archive has no openjdk-17 package at all.
Reading package lists...
Building dependency tree...
Reading state information...
E: Unable to locate package openjdk-17-jdk
No repository line makes the Debian package appear on trixie, so install the Temurin build instead.
sudo apt install -y temurin-17-jdk
Temurin 17 lands in /usr/lib/jvm/temurin-17-jdk-amd64. It registers at priority 1711, below 21 and 25, so it does not take over the default. Call it by its full path to check it:
/usr/lib/jvm/temurin-17-jdk-amd64/bin/java -version
Its banner reports Temurin 17.
openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment Temurin-17.0.20.1+1 (build 17.0.20.1+1)
OpenJDK 64-Bit Server VM Temurin-17.0.20.1+1 (build 17.0.20.1+1, mixed mode, sharing)
Java 11 works the same way with temurin-11-jdk. On our server it took 16 seconds and 326 MB.
Step 5: Oracle JDK 25
Install Oracle JDK only if a vendor requires it, and let the license decide which version you use. Per the Oracle downloads page, JDK 25 updates are free under the No-Fee Terms and Conditions until September 2028.
Oracle JDK 21 is a different case. Its free updates ended in September 2026, and later 21 updates fall under the OTN license, which charges for production use. If you need Java 21, use OpenJDK or Temurin.
Download the current JDK 25 package. The latest path always serves the newest 25 update.
cd /tmp
wget https://download.oracle.com/java/25/latest/jdk-25_linux-x64_bin.deb
Install it with apt rather than dpkg, so the package is tracked like any other and apt remove takes it out cleanly later.
sudo apt install -y ./jdk-25_linux-x64_bin.deb
Once it is installed, the Oracle package takes over, because it registers its tools at priority 419464192 and becomes the default java and javac:
update-alternatives --display java | grep -E "priority|currently"
On our Debian 12 server it outranked the Debian 17 package and both Temurin builds:
link currently points to /usr/lib/jvm/jdk-25.0.4.1-oracle-x64/bin/java
/usr/lib/jvm/java-17-openjdk-amd64/bin/java - priority 1711
/usr/lib/jvm/jdk-25.0.4.1-oracle-x64/bin/java - priority 419464192
/usr/lib/jvm/temurin-21-jdk-amd64/bin/java - priority 2111
/usr/lib/jvm/temurin-25-jdk-amd64/bin/java - priority 2511
Your version banner now reads Java(TM) SE instead of OpenJDK.
java version "25.0.4.1" 2026-08-18 LTS
Java(TM) SE Runtime Environment (build 25.0.4.1+1-LTS-5)
Java HotSpot(TM) 64-Bit Server VM (build 25.0.4.1+1-LTS-5, mixed mode, sharing)
Remove it with sudo apt remove -y jdk-25. When we did, the default fell back to Temurin 25 on its own.
Step 6: Switch Java versions
To change the default, use update-java-alternatives, which moves java, javac and the other tools together. It lives in /usr/sbin, which is not on a regular user’s PATH on Debian, so run it with sudo even for the list:
sudo update-java-alternatives --list
After Steps 1, 2 and 4, our Debian 13 server listed three JDKs from two sources:
java-1.21.0-openjdk-amd64 2111 /usr/lib/jvm/java-1.21.0-openjdk-amd64
java-1.25.0-openjdk-amd64 2511 /usr/lib/jvm/java-1.25.0-openjdk-amd64
temurin-17-jdk-amd64 1711 /usr/lib/jvm/temurin-17-jdk-amd64
Pass a name from the first column to make it the default. With Temurin on Debian 12, the 21 set is temurin-21-jdk-amd64.
sudo update-java-alternatives --set java-1.21.0-openjdk-amd64
With the headless JDK it prints one complaint about jconsole and still exits with status 0.
update-java-alternatives: jdk alternative does not exist: /usr/lib/jvm/java-21-openjdk-amd64/bin/jconsole
jconsole is a GUI tool that only ships in the full openjdk-21-jdk package, so you can ignore the line. Check both tools:
java -version 2>&1 | head -1
javac -version
Both moved to 21:
openjdk version "21.0.12.1" 2026-08-18
javac 21.0.12.1
Why not update-alternatives –set java?
Only one link moves. When we ran it first, java went to 21 while javac stayed on 25:
openjdk version "21.0.12.1" 2026-08-18
javac 25.0.4.1
Anything compiled on that box then fails to start, and a one-line class built with javac 25 and run on java 21 gave us this:
Error: LinkageError occurred while loading main class Mix
java.lang.UnsupportedClassVersionError: Mix has been compiled by a more recent version of the Java Runtime (class file version 69.0), this version of the Java Runtime only recognizes class file versions up to 65.0
Class file version 69 is Java 25 and 65 is Java 21. The interactive sudo update-alternatives --config java has the same problem. Our default Java version guide covers per-tool switching in more detail.
Step 7: Set JAVA_HOME
Most build tools and service wrappers read JAVA_HOME, and a fixed path breaks the next time you switch versions, so derive it from the active java link instead:
echo 'export JAVA_HOME=$(dirname "$(dirname "$(readlink -f /usr/bin/java)")")' | sudo tee /etc/profile.d/java_home.sh
Open a new login shell and print it.
bash -lc 'echo $JAVA_HOME'
With 21 active, it points at the 21 directory:
/usr/lib/jvm/java-21-openjdk-amd64
Switch back to 25 and check again. On Debian 12 with Temurin, the set is called temurin-25-jdk-amd64.
sudo update-java-alternatives --set java-1.25.0-openjdk-amd64
bash -lc 'echo $JAVA_HOME'
You will see the harmless jconsole line again, and JAVA_HOME followed the switch without any edit.
/usr/lib/jvm/java-25-openjdk-amd64
systemd services do not read /etc/profile.d. Set Environment=JAVA_HOME=... in the unit instead, as our Jenkins on Debian guide does for its service.
Step 8: Run Hello.java
Java 25 runs a single source file without a class declaration or a separate compile step, which makes a three-line program the quickest end-to-end test. Create the file:
vim Hello.java
Add these three lines:
void main() {
IO.println("Hello from Java " + Runtime.version() + " on " + System.getProperty("os.name"));
}
Run it straight from source.
java Hello.java
The output on OpenJDK 25:
Hello from Java 25.0.4.1+1-1-deb13u1-Debian on Linux
On Java 21, where this syntax was still a preview feature, the same file fails.
Hello.java:1: error: unnamed classes are a preview feature and are disabled by default.
void main() {
^
(use --enable-preview to enable unnamed classes)
1 error
error: compilation failed
If you see that error after switching versions, the default java is not the one you expect. Run sudo update-java-alternatives --list and set it again. Build tools then pick up the same JDK, whether that is Gradle or Maven.
Disk cost per JDK
A JDK costs 300 to 400 MB of disk whichever build you choose, measured here on 2 vCPU, 4 GB test VMs. “Disk added” is the figure apt printed at install time, and the directory size is du --apparent-size of the JDK under /usr/lib/jvm.
| JDK | Debian | Download | Disk added | JDK directory |
|---|---|---|---|---|
| OpenJDK 25 headless | 13 | 149 MB | 364 MB | 330 MB |
| OpenJDK 21 headless | 13 | 125 MB | 300 MB | 285 MB |
| OpenJDK 17 headless | 12 | 122 MB | 289 MB | not measured |
| Temurin 25 | 12 | 115 MB | 331 MB | 303 MB |
| Temurin 21 | 12 | 177 MB | 361 MB | 345 MB |
| Temurin 17 | 13 | 171 MB | 347 MB | 317 MB |
| Temurin 11 | 13 | 168 MB | 326 MB | not measured |
| Oracle JDK 25 | 12 | 186 MB | 394 MB | 376 MB |
Two JDKs side by side fit on any server, but six add up quickly on a small VM like our test boxes with their 12 GB root disks.
Startup time does not decide the choice. A one-line class compiled for Java 17 started in 22 to 29 ms on the six JDKs we timed, median of 10 runs after 3 warm-ups. The gaps sit within the run-to-run noise of a shared VM.
Pick by support window instead. OpenJDK from the Debian archive is patched through the normal apt upgrade, and Temurin is patched the same way through its repository while covering every LTS release on both Debian versions. On Ubuntu the package names differ, and our Java on Ubuntu guide has them.