JDK 25 landed as the next long-term support release with eight years of patches ahead of it (through September 2033). Both Ubuntu 24.04 and 22.04 carry openjdk-25-jdk in their repositories, so getting the latest LTS Java on Ubuntu is a one-liner. If you need Oracle’s build or Adoptium’s Temurin instead, those are covered here too.
This guide walks through installing JDK 25 via OpenJDK packages, Oracle’s .deb installer, and the Eclipse Temurin repo. It covers setting JAVA_HOME, managing multiple Java versions side by side, testing JDK 25 features like compact source files and module imports, configuring garbage collectors, and production tuning. Every command and output block comes from real Ubuntu systems.
Verified working: March 2026 on Ubuntu 24.04.2 LTS (Noble Numbat) and Ubuntu 22.04 LTS (Jammy Jellyfish), OpenJDK 25.0.2+10, Oracle JDK 25.0.2+10-LTS, Temurin 25.0.2+10
JDK 25 at a Glance
Released September 16, 2025, JDK 25 is the fourth LTS release (after 8, 11, 17, and 21). The latest patch is 25.0.2, released January 20, 2026. Here are the headline features that shipped as final (not preview):
| JEP | Feature | What It Does |
|---|---|---|
| 512 | Compact Source Files | Write void main() {} without a class declaration. Run .java files directly |
| 513 | Flexible Constructor Bodies | Execute validation code before super() calls |
| 506 | Scoped Values | Immutable, thread-safe context sharing (replaces ThreadLocal for virtual threads) |
| 519 | Compact Object Headers | Cuts object headers from 128 to 64 bits, reducing memory overhead |
| 521 | Generational Shenandoah | Low-pause GC with young/old generation separation |
| 510 | Key Derivation Function API | New crypto API for deriving keys from existing secrets |
| 514 | AOT Ergonomics | Simplified ahead-of-time compilation for faster startup |
| 518 | JFR Cooperative Sampling | Lower overhead profiling in Java Flight Recorder |
Full details at the OpenJDK 25 project page.
Install OpenJDK 25 on Ubuntu 24.04
Ubuntu 24.04 ships OpenJDK 25 in its default repositories. No PPAs or third-party repos needed.
sudo apt update
sudo apt install -y openjdk-25-jdk
Verify the installation:
java -version
Ubuntu’s build includes the distribution name in the version string:
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)
The compiler is included:
javac -version
javac 25.0.2
If you only need the runtime (for running Java apps, not compiling), install the lighter JRE package:
sudo apt install -y openjdk-25-jre
The JDK installs to /usr/lib/jvm/java-25-openjdk-amd64 and provides 30 tools including javac, jshell, jlink, jpackage, and jwebserver.
Install OpenJDK 25 on Ubuntu 22.04
Ubuntu 22.04’s default JDK is OpenJDK 11, but the universe repository includes OpenJDK 25 backported from newer releases. The install command is identical:
sudo apt update
sudo apt install -y openjdk-25-jdk
Verify it:
java -version
The build tag shows 22.04:
openjdk version "25.0.2" 2026-01-20
OpenJDK Runtime Environment (build 25.0.2+10-Ubuntu-122.04)
OpenJDK 64-Bit Server VM (build 25.0.2+10-Ubuntu-122.04, mixed mode, sharing)
Same JDK 25.0.2, same features, just compiled against Ubuntu 22.04’s libraries. If the package isn’t found, enable the universe repository first: sudo add-apt-repository universe && sudo apt update.
Install Oracle JDK 25
Oracle provides a .deb package that handles alternative registration automatically. The codebase is identical to OpenJDK, but the license differs (Oracle NFTC, free for production use until September 2028).
Download the package directly from Oracle:
wget https://download.oracle.com/java/25/latest/jdk-25_linux-x64_bin.deb -O /tmp/jdk-25.deb
Install it:
sudo dpkg -i /tmp/jdk-25.deb
Oracle’s build uses the HotSpot branding:
java -version
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. Clean up the downloaded package when done:
rm /tmp/jdk-25.deb
Install Eclipse Temurin 25 (Adoptium)
Temurin is Adoptium’s OpenJDK distribution. It uses the same source as OpenJDK but provides its own builds with independent testing and an apt repository that makes updates automatic.
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
Add the repository for your Ubuntu version. Replace noble with jammy on Ubuntu 22.04:
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
Install Temurin 25:
sudo apt update
sudo apt install -y temurin-25-jdk
Temurin identifies itself in the version output:
java -version
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 repository also carries Temurin 21, 17, 11, and 8 for older LTS needs.
Set JAVA_HOME
Build tools like Maven, Gradle, and Ant, along with application servers like Tomcat and WildFly, need JAVA_HOME pointing to the JDK root. Set it system-wide with a dynamic resolution that follows whichever Java version is currently the 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
Output on Ubuntu 24.04 with OpenJDK 25:
/usr/lib/jvm/java-25-openjdk-amd64
This path updates automatically when you switch versions with update-alternatives. For systemd service files or CI pipelines where you need a fixed path, use the explicit directory:
| JDK Build | JAVA_HOME Path |
|---|---|
| OpenJDK 25 | /usr/lib/jvm/java-25-openjdk-amd64 |
| Oracle JDK 25 | /usr/lib/jvm/jdk-25.0.2-oracle-x64 |
| Temurin 25 | /usr/lib/jvm/temurin-25-jdk-amd64 |
| OpenJDK 21 | /usr/lib/jvm/java-21-openjdk-amd64 |
Manage Multiple Java Versions
Ubuntu’s update-alternatives system handles multiple JDK installations cleanly. You can have OpenJDK 21, OpenJDK 25, Oracle JDK, and Temurin all installed simultaneously and switch between them instantly.
List all registered Java installations:
sudo update-alternatives --list java
With four JDKs installed, you’ll see all four paths:
/usr/lib/jvm/java-21-openjdk-amd64/bin/java
/usr/lib/jvm/java-25-openjdk-amd64/bin/java
/usr/lib/jvm/jdk-25.0.2-oracle-x64/bin/java
/usr/lib/jvm/temurin-25-jdk-amd64/bin/java
Switch to a specific version by setting both java and javac:
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 took effect:
java -version
openjdk version "21.0.10" 2026-01-20
OpenJDK Runtime Environment (build 21.0.10+7-Ubuntu-124.04)
OpenJDK 64-Bit Server VM (build 21.0.10+7-Ubuntu-124.04, mixed mode, sharing)
Switch back to JDK 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 picker that shows all versions with priority numbers:
sudo update-alternatives --config java
Always switch both java and javac together. A version mismatch between compiler and runtime causes subtle bytecode compatibility issues that are painful to debug.
Test JDK 25 Features
Compact Source Files (JEP 512)
One of the most visible changes in JDK 25. You can now write a Java source file with just a main() method, no class wrapper, and run it directly without compiling:
cat > /tmp/Greet.java << 'EOF'
void main() {
System.out.println("Running on Java " + System.getProperty("java.version"));
System.out.println("OS: " + System.getProperty("os.name") + " " + System.getProperty("os.version"));
}
EOF
java /tmp/Greet.java
Output from Ubuntu 24.04:
Running on Java 25.0.2
OS: Linux 6.8.0-35-generic
This is a final feature, not a preview. It works without any flags. Great for quick scripts, prototyping, and teaching.
Module Import Declarations (JEP 511, Preview)
Instead of importing classes one by one, import all public types from a module with a single line:
cat > /tmp/ModTest.java << 'EOF'
import module java.base;
void main() {
var map = Map.of("JDK", "25", "Type", "LTS", "Vendor", "Ubuntu");
map.forEach((k, v) -> System.out.println(k + ": " + v));
}
EOF
java --enable-preview /tmp/ModTest.java
The import module java.base line replaces what would normally be import java.util.Map plus any other java.base imports. Since this is still a preview feature, the --enable-preview flag is required:
JDK: 25
Type: LTS
Vendor: Ubuntu
JShell REPL
jshell provides an interactive environment for testing Java expressions without creating files:
echo 'System.out.println("JShell on " + Runtime.version());' | jshell -q
jshell> JShell on 25.0.2+10-Ubuntu-124.04
Run jshell without arguments for an interactive session where you can test classes, methods, and expressions on the fly.
Built-in Web Server
JDK 25 includes jwebserver for quick file serving during development. It serves the current directory over HTTP:
jwebserver -p 8080 -b 0.0.0.0
Access it at http://your-server:8080/. Strictly for development and testing, not production use. Press Ctrl+C to stop.
Traditional Compile and Run
The standard workflow still works for structured projects:
cat > /tmp/Hello.java << 'EOF'
public class Hello {
public static void main(String[] args) {
System.out.println("Hello from " + System.getProperty("java.vendor") + " JDK " + System.getProperty("java.version"));
Runtime rt = Runtime.getRuntime();
System.out.println("Available processors: " + rt.availableProcessors());
System.out.println("Max memory: " + (rt.maxMemory() / 1024 / 1024) + " MB");
}
}
EOF
javac /tmp/Hello.java -d /tmp
java -cp /tmp Hello
Hello from Ubuntu JDK 25.0.2
Available processors: 2
Max memory: 980 MB
Garbage Collector Selection
JDK 25 ships three production garbage collectors. G1 is the default and works well for most workloads. ZGC and Shenandoah target specialized scenarios.
| Collector | JVM Flag | Best For |
|---|---|---|
| G1 (default) | -XX:+UseG1GC | General purpose with balanced throughput and latency |
| ZGC | -XX:+UseZGC | Sub-millisecond pauses, large heaps up to multi-terabytes |
| Shenandoah | -XX:+UseShenandoahGC | Low-pause with generational mode (new in JDK 25 via JEP 521) |
Check which GC is active:
java -XX:+PrintFlagsFinal -version 2>&1 | grep "Use.*GC " | grep true
bool UseG1GC = true {product} {ergonomic}
Switch to ZGC for a latency-sensitive application:
java -XX:+UseZGC -jar your-app.jar
Enable GC logging to compare collectors under your workload:
java -Xlog:gc*:file=/var/log/app-gc.log:time,uptime,level,tags -jar your-app.jar
OpenJDK vs Oracle JDK vs Temurin
| Aspect | OpenJDK (Ubuntu) | Oracle JDK | Temurin (Adoptium) |
|---|---|---|---|
| Source | OpenJDK upstream | Same source | Same source |
| License | GPLv2 + Classpath Exception | Oracle NFTC (free until Sep 2028) | GPLv2 + Classpath Exception |
| Vendor | Ubuntu | Oracle Corporation | Eclipse Adoptium |
| VM | OpenJDK 64-Bit Server VM | Java HotSpot(TM) 64-Bit Server VM | OpenJDK 64-Bit Server VM |
| Install path | java-25-openjdk-amd64 | jdk-25.0.2-oracle-x64 | temurin-25-jdk-amd64 |
| Updates via apt | Yes (Ubuntu repos) | No (manual .deb download) | Yes (Adoptium repo) |
| Ubuntu 24.04 | Default repos | Manual .deb | Adoptium repo |
| Ubuntu 22.04 | Universe repo | Manual .deb | Adoptium repo |
Performance is identical across all three builds since they share the same codebase. Choose based on your update and licensing preferences. OpenJDK from Ubuntu repos is the simplest. Temurin gives you an independent update channel. Oracle JDK requires manual upgrades but includes commercial support options.
Production Configuration
Pin the JDK in service files. Use the absolute path in your systemd unit files to prevent version drift when system updates install a newer JDK:
Environment="JAVA_HOME=/usr/lib/jvm/java-25-openjdk-amd64"
ExecStart=/usr/lib/jvm/java-25-openjdk-amd64/bin/java -jar /opt/myapp/app.jar
Set explicit heap limits. JDK 25 allocates 25% of system RAM by default. In containers, set bounds to match the container's memory limit:
java -Xms512m -Xmx2g -jar app.jar
Use AOT caching for faster startup (JEP 514). Create a training run that captures compilation data, then reuse it for instant startup:
java -XX:AOTCacheOutput=app.aot -jar app.jar
java -XX:AOTCache=app.aot -jar app.jar
Keep the JDK updated. Security patches for LTS releases come quarterly (January, April, July, October). With OpenJDK from Ubuntu repos or Temurin from Adoptium, a regular sudo apt upgrade keeps you current.
Uninstall
Remove OpenJDK 25:
sudo apt remove --purge openjdk-25-jdk openjdk-25-jre
Remove Oracle JDK 25:
sudo dpkg --purge jdk-25
Remove Temurin 25:
sudo apt remove --purge temurin-25-jdk
After removal, verify the default Java version updated correctly: java -version. If another version is installed, it becomes the new default automatically.
For installing Java on other Linux distributions, see our guides for JDK 25 on Debian 13/12, Java on Rocky Linux/AlmaLinux, or Java on RHEL/Rocky/AlmaLinux.