Skip to content
Happy Programming Guide
Start learning
Java

What’s New in Java 25 LTS

Java 25 is the current long-term release. Flexible constructors, compact source files, module imports and scoped values are final; here is what each means and what to check before moving from 21.

A laptop with a cup of coffee beside it

Java 25, released in September 2025, is the long-term-support release that follows Java 21, and it will be supported for years by every major vendor. Several features that spent two or three releases in preview are now final: flexible constructor bodies, compact source files with instance main methods, module import declarations and scoped values. Below is what each does, what is still in preview, and how to move a Java 21 project across.

Compact source files and instance main#

Hello World no longer needs a class declaration, a static main, or a String array:

JAVA
void main() {
    IO.println("Hello, Java 25");
}

Save that as Hello.java and run java Hello.java. The compiler wraps it in an implicit class; IO.println and IO.readln are new convenience methods so beginners do not start with System.out.println. When the program grows, you add the class declaration and nothing else changes. This is final in 25 after several rounds of preview, and it makes Java a reasonable first language again.

Module import declarations#

JAVA
import module java.base;      // every exported package of the module, one line

void main() {
    List<String> names = new ArrayList<>();     // no individual imports needed
    Map<String, Integer> counts = new HashMap<>();
}

Importing a whole module replaces a wall of import java.util.* lines. Compact source files import java.base automatically, which is why the example above needs no imports at all. In larger programs, explicit single-type imports are still clearer; this is for scripts and quick work.

Flexible constructor bodies#

Statements may now appear before super(...) or this(...) in a constructor, as long as they do not touch the object being built. That lets you validate arguments, or compute values, before delegating:

JAVA
class PositiveValue extends Value {
    PositiveValue(int n) {
        if (n <= 0) throw new IllegalArgumentException("must be positive");   // now allowed here
        super(n);
    }
}

Previously this required a static helper method to do the check inside the super call’s argument. You can also assign fields of the subclass before calling super, which removes a class of bugs where a superclass constructor calls an overridden method that reads an uninitialised field.

Scoped values#

ThreadLocal gives each thread a mutable slot, which is expensive and awkward with millions of virtual threads. Scoped values bind an immutable value for the duration of a call and make it visible to everything that call invokes:

JAVA
static final ScopedValue<User> CURRENT_USER = ScopedValue.newInstance();

void handle(Request req) {
    ScopedValue.where(CURRENT_USER, authenticate(req)).run(() -> process(req));
}

void process(Request req) {
    User u = CURRENT_USER.get();       // available here, and in anything process calls
}

The binding ends when run returns, cannot be changed from inside, and is inherited by child threads created with structured concurrency. For request context, tenant IDs and the like, this is what to use in new code.

Runtime improvements#

  • Compact object headers are now a supported feature, enabled with -XX:+UseCompactObjectHeaders. Each object’s header shrinks from 12 bytes to 8, which reduces heap use and improves cache behaviour for object-heavy workloads.
  • Ahead-of-time method profiling and command-line ergonomics extend the AOT cache from Java 24: a training run records which methods are hot, and later starts use that profile so the JIT warms up faster. Start-up-sensitive services benefit most.
  • Generational Shenandoah is a product feature; the Shenandoah collector now separates young and old objects like the other collectors.
  • Key derivation functions get a standard API for the cryptography that modern protocols need.

Still in preview#

These need --enable-preview and may change:

  • Structured concurrency, in its fifth preview with a reworked API. The idea — treat a group of concurrent tasks as one unit that succeeds or fails together — is settled; the shape of the API is still being finalised.
  • Primitive types in patterns, so switch and instanceof work with int and friends.
  • Stable values, a way to declare a field that is set once, lazily, and then treated as a constant by the JIT.
  • PEM encoding of cryptographic objects.

The Vector API continues in incubation, as it has for many releases, waiting on Project Valhalla.

Moving from Java 21#

  1. Update the build tool and plugins first. Maven compiler and Gradle need versions that know about 25’s class-file format.
  2. Update annotation processors, particularly Lombok, MapStruct and anything that generates code; they break on every new release until updated.
  3. Check for removed APIs. The 32-bit x86 port is gone, some security-manager remnants are gone, and a few long-deprecated methods were removed. The jdeprscan tool lists what your code touches.
  4. Run the tests. Then run the application with -XX:+UseCompactObjectHeaders and measure memory; for many services it is a free win.
Terminal
jdeprscan --release 25 target/classes
java -XX:+UseCompactObjectHeaders -jar app.jar

Questions people ask#

How long is Java 25 supported?

Vendors offer at least five years of updates, and several offer eight or more. Check the specific distribution you deploy.

Should I move from 21 to 25 now?

For new projects, yes. For existing ones, when your frameworks and libraries have released versions tested on 25, which for the major ones happened within months of release.

Is Java 25 faster than 21?

Generally, yes, without code changes: JIT improvements, compact headers and better garbage collection. The size of the gain depends heavily on the workload.

What happened to Java 22, 23 and 24?

Short-term releases, each supported for six months. They delivered the previews that became final in 25. Nobody should still be running them.

Where to go next#

Java virtual threads: how to use themRead next

Keep reading

Java

Java Not Working in VS Code

No IntelliSense, "cannot find symbol" on everything, or the run button does nothing? VS Code needs a JDK it can find and…

4 min read

Java

Java Input and Output (I/O)

Reading and writing files in Java: the modern Files and Path API, buffered streams for large files, reading keyboard input, and try-with-resources.

4 min read

Keep going — pick your next guide

The fastest way to improve is to read one guide, then build the thing it describes. Start with the basics, or jump straight to a project.

Ask a question or share what worked

Your email address will not be published. Required fields are marked *