Debian

Install Java 25 (JDK 25) on Debian 13 / Debian 12

JDK 25 is the new long-term support release, which means it gets security patches and bug fixes until at least September 2033. If you’re still running JDK 17 or 21 in production, this is the next LTS worth upgrading to. Debian 13 (Trixie) ships OpenJDK 25 in its default repos, making the install trivial. Debian 12 (Bookworm) needs a bit more work since its repos only carry OpenJDK 17.

Original content from computingforgeeks.com - post 164541

This guide covers three installation methods: OpenJDK from Debian repos, Oracle JDK from Oracle’s .deb package, and Eclipse Temurin from the Adoptium repository. It also walks through switching between multiple Java versions, setting JAVA_HOME correctly, testing JDK 25 features like compact source files and module imports, and configuring garbage collectors. All code blocks use real output from actual Debian systems.

Tested March 2026 on Debian 13.0 (Trixie) with OpenJDK 25.0.2+10 and Debian 12.13 (Bookworm) with Oracle JDK 25.0.2+10-LTS and Temurin 25.0.2+10

What’s New in JDK 25

JDK 25 was released on September 16, 2025, with the latest patch (25.0.2) landing on January 20, 2026. As an LTS release, it replaces JDK 21 as the recommended version for production workloads. The release includes 18 JEPs (Java Enhancement Proposals), with these being the most significant final features:

JEPFeatureWhy It Matters
506Scoped ValuesThread-safe context sharing, replaces ThreadLocal for virtual threads
510Key Derivation Function APICryptographic API for generating secure keys from existing secrets
511Module Import DeclarationsSingle import module java.base; replaces dozens of import lines
512Compact Source FilesWrite void main() {} without a class wrapper, great for scripts and learning
513Flexible Constructor BodiesExecute code before super() calls for argument validation
514AOT Command-Line ErgonomicsFaster application startup via -XX:AOTCacheOutput
519Compact Object HeadersReduces object header from 128 to 64 bits, saving memory
521Generational ShenandoahLow-pause GC now separates young/old generations for better throughput

For the complete list, see the OpenJDK 25 project page.

Prerequisites

  • Debian 13 (Trixie) or Debian 12 (Bookworm)
  • Root or sudo access
  • 512 MB RAM minimum (1 GB+ recommended for compilation)
  • 400 MB disk space for JDK installation
  • Tested on: OpenJDK 25.0.2+10 (Debian 13), Oracle JDK 25.0.2+10-LTS (Debian 12), Temurin 25.0.2+10 (Debian 12)

Install OpenJDK 25 on Debian 13

Debian 13 includes OpenJDK 25 in its default repositories. No extra repos needed.

Update the package index:

sudo apt update

Install the full JDK (compiler, runtime, and development tools):

sudo apt install -y openjdk-25-jdk

If you only need the runtime (no compiler or dev tools), install the JRE instead:

sudo apt install -y openjdk-25-jre

Verify the installation:

java -version

The version string confirms OpenJDK 25.0.2:

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

Check the compiler version too:

javac -version

Output:

javac 25.0.2

The JDK installs to /usr/lib/jvm/java-25-openjdk-amd64 and includes 30 tools: javac, jshell, jlink, jpackage, jwebserver, and more.

Install JDK 25 on Debian 12

Debian 12’s default repos only ship OpenJDK 17. For JDK 25, you have three options: Oracle JDK (official .deb package), Eclipse Temurin from the Adoptium repository, or a manual tarball install. The first two methods are covered here.

Option A: Oracle JDK 25

Oracle provides a .deb package that handles all the alternative registration automatically. Download it from Oracle’s servers:

wget https://download.oracle.com/java/25/latest/jdk-25_linux-x64_bin.deb -O /tmp/jdk-25.deb

Install the package:

sudo dpkg -i /tmp/jdk-25.deb

The .deb package registers itself with the alternatives system and sets Java 25 as the default. Verify it:

java -version

Oracle’s build identifies itself differently from OpenJDK:

java version "25.0.2" 2026-01-20 LTS
Java(TM) SE Runtime Environment (build 25.0.2+10-LTS-69)
Java HotSpot(TM) 64-Bit Server VM (build 25.0.2+10-LTS-69, mixed mode, sharing)

Oracle JDK installs to /usr/lib/jvm/jdk-25.0.2-oracle-x64. The Oracle NFTC license allows free use in production until September 2028.

Option B: Eclipse Temurin (Adoptium)

Temurin is an OpenJDK build maintained by the Eclipse Foundation under the Adoptium project. It gets regular updates and is fully open source under GPLv2.

Add the Adoptium GPG key and repository:

sudo apt install -y wget apt-transport-https gpg
wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor | sudo tee /usr/share/keyrings/adoptium.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/adoptium.gpg] https://packages.adoptium.net/artifactory/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/adoptium.list

Update the package index and install Temurin 25:

sudo apt update
sudo apt install -y temurin-25-jdk

Check the version:

java -version

Temurin’s version string includes the build identifier:

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

Temurin installs to /usr/lib/jvm/temurin-25-jdk-amd64. The Adoptium repo also provides Temurin 21, 17, 11, and 8 if you need older LTS versions alongside 25.

Set JAVA_HOME

Many build tools (Maven, Gradle, Ant) and application servers (Tomcat, WildFly) need JAVA_HOME to point to the JDK installation directory. Set it system-wide:

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

This approach dynamically resolves the path based on the current default Java, so it stays correct even when you switch versions. Verify it:

echo $JAVA_HOME

On Debian 13 with OpenJDK 25:

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

If you need a fixed path (common in systemd service files or CI pipelines), set it explicitly based on your installation:

DistributionJAVA_HOME Path
OpenJDK 25 (Debian 13)/usr/lib/jvm/java-25-openjdk-amd64
Oracle JDK 25 (Debian 12)/usr/lib/jvm/jdk-25.0.2-oracle-x64
Temurin 25 (Debian 12)/usr/lib/jvm/temurin-25-jdk-amd64

Switch Between Multiple Java Versions

Debian’s update-alternatives system handles multiple Java installations cleanly. When you install OpenJDK 21 alongside 25, both register as alternatives.

On Debian 13, install OpenJDK 21 alongside 25:

sudo apt install -y openjdk-21-jdk

List all registered Java installations:

sudo update-alternatives --list java

Both versions appear:

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

Switch to Java 21:

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

Confirm the switch:

java -version

Now shows Java 21:

openjdk version "21.0.10" 2026-01-20
OpenJDK Runtime Environment (build 21.0.10+7-Debian-1deb13u1)
OpenJDK 64-Bit Server VM (build 21.0.10+7-Debian-1deb13u1, mixed mode, sharing)

Switch back to Java 25:

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

For an interactive menu that lets you pick from all installed versions:

sudo update-alternatives --config java

Remember to switch both java and javac together, otherwise you’ll compile with one version and run with another.

Test JDK 25 Features

A quick way to verify that your JDK 25 installation is fully functional and taking advantage of new features.

Compact Source Files (JEP 512)

JDK 25 lets you write a Java file without the class boilerplate. Create a file with just a main() method:

cat > /tmp/Greet.java << "EOF"
void main() {
    System.out.println("Compact source file works on Java " + System.getProperty("java.version"));
}
EOF

Run it directly without compiling first:

java /tmp/Greet.java

Output confirms the feature works:

Compact source file works on Java 25.0.2

No public class, no String[] args, no compilation step. This is a production feature in JDK 25, not a preview.

Module Import Declarations (JEP 511, Preview)

Instead of importing java.util.List, java.util.Map, and every other class individually, you can import an entire module:

cat > /tmp/ModuleTest.java << "EOF"
import module java.base;

void main() {
    List items = List.of("Java", "25", "LTS");
    items.forEach(System.out::println);
}
EOF

Since this is a preview feature, run it with --enable-preview:

java --enable-preview /tmp/ModuleTest.java

Each element prints on its own line:

Java
25
LTS

JShell Interactive Testing

jshell is the built-in REPL for quick Java experiments:

echo 'System.out.println("JShell on JDK " + Runtime.version());' | jshell -q

Prints the full runtime version:

jshell> JShell on JDK 25.0.2+10-Debian-1deb13u2

Built-in Web Server

JDK 25 includes jwebserver, a minimal HTTP server for quick file serving during development:

jwebserver -p 8888 -b 0.0.0.0

It serves the current directory on port 8888. Not meant for production, but handy for local testing and sharing files on a network. Press Ctrl+C to stop it.

Garbage Collector Configuration

JDK 25 defaults to the G1 garbage collector. Three production GCs are available, each suited to different workloads:

GCFlagBest For
G1 (default)-XX:+UseG1GCGeneral purpose, balanced throughput and latency
ZGC-XX:+UseZGCSub-millisecond pause times, large heaps (multi-TB)
Shenandoah-XX:+UseShenandoahGCLow-pause with generational mode (new in JDK 25, JEP 521)

Check which GC is active in your current JVM:

java -XX:+PrintFlagsFinal -version 2>&1 | grep "Use.*GC " | grep true

Default output shows G1 enabled:

     bool UseG1GC                                  = true                                      {product} {ergonomic}

Enable the Generational Shenandoah GC (new in JDK 25) for workloads that need consistent low pauses:

java -XX:+UseShenandoahGC -XX:+PrintFlagsFinal -version 2>&1 | grep "UseShenandoahGC"

OpenJDK vs Oracle JDK vs Temurin

AspectOpenJDK (Debian)Oracle JDKTemurin (Adoptium)
CodebaseOpenJDK sourceSame OpenJDK sourceSame OpenJDK source
LicenseGPLv2 + ClasspathOracle NFTC (free until Sep 2028)GPLv2 + Classpath
Vendor stringDebianOracle CorporationTemurin
VM nameOpenJDK 64-Bit Server VMJava HotSpot(TM) 64-Bit Server VMOpenJDK 64-Bit Server VM
Install path (Debian)/usr/lib/jvm/java-25-openjdk-amd64/usr/lib/jvm/jdk-25.0.2-oracle-x64/usr/lib/jvm/temurin-25-jdk-amd64
Debian 13 repoYesNo (manual .deb)Via Adoptium repo
Debian 12 repoNo (only JDK 17)No (manual .deb)Via Adoptium repo
LTS patchesDebian security teamOracle (requires NFTC/OTN)Adoptium community

All three builds produce identical bytecode and run the same applications. The choice comes down to licensing preferences and how you want to receive updates. For Debian 13, the default OpenJDK package is the simplest. For Debian 12, Temurin gives you the easiest update path via apt upgrade.

Uninstall or Downgrade

Remove OpenJDK 25 on Debian 13:

sudo apt remove --purge openjdk-25-jdk openjdk-25-jre

Remove Oracle JDK 25 on Debian 12:

sudo dpkg --purge jdk-25

Remove Temurin 25:

sudo apt remove --purge temurin-25-jdk

After removing a Java version, check that the alternatives system updated correctly:

java -version

If another version is still installed, it becomes the new default automatically.

Production Tips

Pin the JDK version in CI pipelines. Use the full path (/usr/lib/jvm/java-25-openjdk-amd64/bin/java) in systemd service files and CI configs instead of relying on update-alternatives. A system update that installs a newer JDK can silently change the default and break your application.

Set heap sizes explicitly. JDK 25's ergonomics pick 25% of system RAM for the heap by default. For containers, set -Xms and -Xmx to match the container's memory limit:

java -Xms512m -Xmx2g -jar app.jar

Enable AOT caching for faster startup. JDK 25's AOT improvements (JEP 514) let you create a cache of compiled code that speeds up subsequent launches. Generate a cache with a training run, then use it in production:

java -XX:AOTCacheOutput=app.aot -jar app.jar
java -XX:AOTCache=app.aot -jar app.jar

Monitor GC behavior. Enable GC logging to find the right collector and tuning for your workload:

java -Xlog:gc*:file=/var/log/app-gc.log:time,uptime,level,tags -jar app.jar

For applications like Java on Rocky Linux/AlmaLinux, the same JDK 25 features apply with different package names. If you're deploying Java web applications, see our guides on Java installation on Ubuntu/Debian for Ubuntu-specific instructions, or OpenJDK on Debian for an OpenJDK-focused walkthrough.

Related Articles

Debian Mount Google Drive on Ubuntu/Debian and Upload Files Security Install and Configure Firewalld on Debian 13 / Ubuntu 24.04 Debian How To Install LAMP Stack on Debian 12/11/10 Databases Install Metabase with Systemd on Debian 12/11/10

Leave a Comment

Press ESC to close