Java6 min read

What's New in Java 25: The Complete Guide

18 JEPs, LTS release, and Java turns 30. Everything you need to know.

Overview

Java 25 (JDK 25) reached General Availability on September 16, 2025, and it’s a big one. It’s the new Long-Term Support (LTS) release — the first since JDK 21 in September 2023 — with at least 8 years of commercial support from Oracle.

Java Turns 30

Java celebrated its 30th anniversary in 2025. From applets to microservices, from J2EE to virtual threads — three decades of evolution, and Java 25 proves the language isn’t slowing down.

JDK 25 delivers 18 JEPs across these categories:

  • 7 Finalized features (production-ready)
  • 4 Preview features (opt-in with --enable-preview)
  • 1 Incubator (Vector API, 10th round)
  • 1 Experimental (JFR CPU-Time Profiling)
  • 3 JFR enhancements
  • 2 Removals

Language Features

Compact Source Files & Instance Main Methods (JEP 512) — Final

After previewing across JDK 21–24, the simplified entry point is now official. No more public static void main(String[] args) for simple programs.

Before (Java 8–24)

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

After (Java 25)

void main() {
    println("Hello, World!");
}

Three lines. No class declaration, no static, no String[] args, no System.out. Perfect for scripting, teaching, and quick prototypes.

Module Import Declarations (JEP 511) — Final

Import all exported packages from a module in one line:

Module Imports

// Before: multiple import statements
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

// After: one module import covers everything
import module java.base;

You don’t need to modularize your own code to use this. import module java.base gives you access to java.util, java.io, java.time, and all other java.base packages in one shot.

Flexible Constructor Bodies (JEP 513) — Final

You can now execute statements before calling super() or this() in constructors. A long-awaited change.

Validate Before super()

public class Employee extends Person {

    public Employee(String name, int age) {
        // Validate BEFORE calling super — now legal in Java 25!
        if (age < 18) {
            throw new IllegalArgumentException("Must be 18+");
        }
        super(name, age);
    }
}

Primitive Types in Patterns (JEP 507) — 3rd Preview

Pattern matching now works with int, long, double, and other primitives in instanceof and switch:

Primitive Patterns in switch

// switch with int patterns — new in Java 25 (preview)
String classify(int statusCode) {
    return switch (statusCode) {
        case 200        -> "OK";
        case 301, 302  -> "Redirect";
        case 400        -> "Bad Request";
        case 404        -> "Not Found";
        case 500        -> "Server Error";
        case int n when n >= 200 && n < 300 -> "Success";
        case int n when n >= 400 && n < 500 -> "Client Error";
        default         -> "Unknown";
    };
}

Performance & Runtime

Compact Object Headers (JEP 519) — Final

Object headers in the HotSpot JVM are reduced from 96–128 bits down to 64 bits on 64-bit architectures. This is automatic — no code changes needed.

Ahead-of-Time Method Profiling (JEP 515) — Final

Java apps typically run slow at startup while the JIT compiler “warms up” by profiling which methods are hot. JEP 515 saves those profiles from a previous run into an AOT cache, so the JIT can generate native code immediately on next startup.

AOT Cache with Method Profiles

# Create AOT cache in one step (JEP 514 simplifies this)
java -XX:AOTCacheOutput=app.aot -jar myapp.jar

# Run with cached profiles — instant warmup
java -XX:AOTCache=app.aot -jar myapp.jar

Generational Shenandoah (JEP 521) — Final

The Shenandoah garbage collector now officially supports generational mode, promoting it from experimental to production-ready.

Enable Generational Shenandoah

java -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -jar myapp.jar

Benefits: improved throughput, better load-spike resilience, and more efficient memory utilization compared to non-generational mode.

Concurrency & Data Sharing

Scoped Values (JEP 506) — Final

ScopedValue is finalized after five previews. It provides a way to share immutable data with callees within and across threads — like ThreadLocal but safer, faster, and immutable.

ScopedValue Example

private static final ScopedValue<String> USER =
    ScopedValue.newInstance();

// Set the value for a scope
ScopedValue.where(USER, "admin").run(() -> {
    handleRequest();  // USER.get() returns "admin" here
});

void handleRequest() {
    String currentUser = USER.get();  // "admin"
    // Any method called from here can also access USER
}

Structured Concurrency (JEP 505) — 5th Preview

Groups of related tasks running in different threads are treated as a single unit of work. If one subtask fails, the others are automatically cancelled.

Structured Concurrency

// Fetch user and orders in parallel — if either fails, both cancel
try (var scope = StructuredTaskScope.open()) {

    Subtask<User> userTask = scope.fork(() -> fetchUser(userId));
    Subtask<List<Order>> ordersTask = scope.fork(() -> fetchOrders(userId));

    scope.join();  // Wait for both

    return new UserProfile(userTask.get(), ordersTask.get());
}

Stable Values (JEP 502) — Preview

A StableValue can be set only once and is then treated as a constant by the JVM, enabling constant-folding optimizations. Perfect for lazy initialization.

Stable Values

// Lazy, thread-safe, one-time initialization
private static final StableValue<DatabasePool> DB_POOL =
    StableValue.of(() -> createExpensivePool());

// First call initializes, all subsequent calls return the same instance
DatabasePool pool = DB_POOL.get();

Security

Key Derivation Function API (JEP 510) — Final

A new API for deriving additional cryptographic keys from a secret key. Supports HKDF (HMAC-based Extract-and-Expand) and Argon2.

Key Derivation

import javax.crypto.KDF;

KDF kdf = KDF.getInstance("HKDF-SHA256");
SecretKey derivedKey = kdf.deriveKey(
    "AES",
    new HKDFParameterSpec.Builder(
        secretKey, salt, info
    ).build()
);

This is a foundational piece for Java’s post-quantum cryptography support — used internally by ML-KEM and TLS 1.3 Hybrid Key Exchange.

PEM Encodings of Cryptographic Objects (JEP 470) — Preview

A new API for encoding/decoding keys, certificates, and CRLs in the widely used PEM format (.pem files). No more bouncing between byte arrays and Base64 manually.

Observability (JFR)

Java Flight Recorder gets three significant upgrades in JDK 25:

JFR Enhancements

JEPFeatureWhat It Does
518Cooperative SamplingWalks call stacks only at safepoints, reducing bias and improving stability
520Method Timing & TracingRecords execution times for specific methods without modifying source code
509CPU-Time Profiling (Experimental)More accurate CPU-time capture on Linux using kernel CPU timers

For QA teams, JFR Method Timing is especially useful — you can identify slow methods in production without adding any logging or instrumentation to your code.

Other Changes

Vector API (JEP 508) — 10th Incubator

Still incubating (waiting for Project Valhalla), but now links to native math libraries via the Foreign Function and Memory API. Auto-vectorizes Float16 operations on x64 CPUs.

Removal of 32-bit x86 Port (JEP 503)

All source code and build support for 32-bit x86 is removed. If you’re still running 32-bit Java… it’s time.

Other Notable Changes

  • ZGC string deduplication now skips young, short-lived strings for better performance
  • New SHAKE128-256 and SHAKE256-512 MessageDigest algorithms added
  • Post-quantum cryptography (PQC) support for improved security
  • Removal of the experimental Graal JIT compiler

All 18 JEPs at a Glance

JEPFeatureStatus
506Scoped ValuesFinal
510Key Derivation Function APIFinal
511Module Import DeclarationsFinal
512Compact Source Files & Instance Main MethodsFinal
513Flexible Constructor BodiesFinal
519Compact Object HeadersFinal
521Generational ShenandoahFinal
507Primitive Types in Patterns3rd Preview
505Structured Concurrency5th Preview
502Stable ValuesPreview
470PEM EncodingsPreview
508Vector API10th Incubator
509JFR CPU-Time ProfilingExperimental
514AOT Command-Line ErgonomicsFinal
515AOT Method ProfilingFinal
518JFR Cooperative SamplingFinal
520JFR Method Timing & TracingFinal
503Remove 32-bit x86 PortRemoval

Why Should QA Engineers Care?