Computer Software Today

Empowering you with the best news, learning and tech resources

.NET & Java

Java 25 LTS: What’s New and Should You Upgrade from 17 or 21?

Java 25 is the current Long Term Support release of Java, generally available since September 16, 2025, with Oracle Premier Support through September 2030. It finalizes compact source files, module imports, flexible constructor bodies, scoped values, and compact object headers. If you’re on Java 17 or 21, it’s time to plan the move.

Below I cover the JEPs that matter in production code, the support dates you need to know (two of them have already passed), a checklist for upgrading, and a quick look at Java 26 and 27, which have both shipped since.

What is Java 25 and why does the LTS label matter?

Java 25 (JDK 25) is the LTS release that replaces Java 21 as the default target for new production work. LTS means multi-year vendor support, which is what enterprises standardize on.

Java ships a new feature release every six months, every March and September. Most of those releases get six months of updates and then they’re done. Every two years one release is designated LTS, and vendors such as Oracle, Eclipse Adoptium, Microsoft, Amazon, Red Hat, and Azul support it for years. Java 17 (2021) and Java 21 (2023) are the previous two. Java 25 arrived on September 16, 2025, with 18 JEPs.

In my experience, most shops treat the non-LTS releases as previews of what’s coming, then move their fleet from one LTS to the next. That’s a sensible policy. The catch is that it turns every LTS upgrade into a jump of four years of changes, and that’s where the surprises hide.

What’s new in Java 25 that working developers will notice?

Compact source files with instance main methods, module import declarations, flexible constructor bodies, final scoped values, and compact object headers. Startup-focused AOT improvements round it out.

Compact source files and instance main methods (JEP 512)

A Java program no longer needs a class declaration or public static void main(String[] args). There’s also a new java.lang.IO class for simple console I/O:

// Hello.java
void main() {
    IO.println("Hello from Java 25");
}

Run it with java Hello.java. Teachers will love it, and so will anyone writing small utility scripts who used to reach for Python just to avoid the ceremony.

Module import declarations (JEP 511)

import module java.base; imports every package a module exports in a single line. It’s most useful in scripts and prototypes. In real application code I’d still use explicit imports.

Flexible constructor bodies (JEP 513)

You can now run statements before calling super(...) or this(...), as long as they don’t touch the object under construction. That means validating arguments before you hand them to the parent class:

class Employee extends Person {
    Employee(String name, int age) {
        if (age < 18) throw new IllegalArgumentException("age");
        super(name, age);
    }
}

Scoped values (JEP 506)

Scoped values are now final. They’re an immutable, bounded alternative to ThreadLocal that works well with virtual threads, which is a good fit for things like request IDs and the current tenant:

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

ScopedValue.where(REQUEST_ID, "abc-123").run(() -> handleRequest());

Structured concurrency is still a preview feature in 25. I wouldn’t put preview features into production code that has to last the full life of an LTS.

Which Java 25 changes improve performance and memory?

Compact object headers can shrink heap use noticeably, and the new AOT cache workflow speeds up startup. Generational Shenandoah is now a supported product feature as well.

Compact object headers (JEP 519) reduce every object’s header on 64-bit JVMs from 12 bytes to 8. In Java 25 it’s a supported product option but it’s off by default, so you turn it on with -XX:+UseCompactObjectHeaders. The JEP reports 10 to 20 percent less heap in testing, and HappyCoders summarizes production reports in a similar range. Java 27 makes it the default. If you run large heaps full of small objects (and most Spring apps fit that description), test it under load.

AOT command-line ergonomics (JEP 514) makes the ahead-of-time cache from Project Leyden a one-step job. A training run writes the cache, and production runs read it:

java -XX:AOTCacheOutput=app.aot -jar app.jar   # training run
java -XX:AOTCache=app.aot -jar app.jar         # production run

AOT method profiling (JEP 515) stores profiling data in that cache too, so the JIT warms up faster. For containers that scale up and down often, startup and warmup time is real money.

Java 25 also adds JFR improvements (CPU-time profiling as an experimental feature, plus method timing and tracing), a final Key Derivation Function API, and drops the 32-bit x86 port entirely.

What is the Java 25 support timeline compared to Java 17 and 21?

Oracle supports Java 25 with Premier Support until September 2030 and Extended Support until September 2033. Java 17’s Premier Support already ended in September 2026.

Release GA Oracle Premier Support Oracle Extended Support Eclipse Temurin (at least)
Java 17 (LTS) Sep 2021 Sep 2026 (ended) Sep 2029 Oct 2027
Java 21 (LTS) Sep 2023 Sep 2028 Sep 2031 Dec 2029
Java 25 (LTS) Sep 2025 Sep 2030 Sep 2033 Sep 2031
Java 26 Mar 2026 Sep 2026 (ended) None n/a
Java 27 Sep 2026 Mar 2027 None Mar 2027

Sources: Oracle Java SE Support Roadmap and Adoptium’s Temurin support page.

There’s a licensing detail here that catches people out. Oracle JDK 21 updates were free for production use under the No-Fee Terms and Conditions license for a limited window only. Oracle’s roadmap now says Oracle JDK 21 releases from October 20, 2026 onward fall under the OTN license, which needs a paid subscription for most production use. Oracle JDK 25’s free updates are planned to run through September 2028. If cost matters, an OpenJDK build such as Temurin avoids the question entirely.

Timeline of Oracle Java support: Java 17 Premier to Sep 2026, Java 21 to Sep 2028, Java 25 to Sep 2030 with extended support to 2033, Java 26 and 27 six-month releases
Oracle Premier and Extended Support windows for Java 17, 21 and 25, plus the short-lived Java 26 and 27 releases.

Should you upgrade from Java 17 or Java 21 to Java 25?

From Java 17, yes: start now, because Oracle’s Premier Support has ended and you’re four years behind. From Java 21 there’s less urgency, but plan the move within the next year or so.

Coming from 17, you also pick up everything from 18 through 24: virtual threads, pattern matching for switch, record patterns, sequenced collections, generational ZGC, the Foreign Function and Memory API, unnamed variables (_), stream gatherers, and virtual threads that no longer pin a carrier thread inside synchronized blocks (JDK 24). That last one fixed the main reason teams hesitated to adopt virtual threads in 21.

Coming from 21, the gains are smaller but real: the pinning fix, compact object headers, the AOT cache, scoped values, and the language cleanups above. Java 21 is supported for years yet, so you can schedule this upgrade instead of rushing it. If you run Oracle JDK 21 and don’t have a subscription, though, the October 2026 licensing change moves it up the list.

I wouldn’t go straight to Java 27 for production. It’s a six-month release. Run your test suite against it to see what’s coming, and deploy on 25.

What can break when moving from Java 17 or 21 to 25?

The usual suspects are annotation processors that silently stop running, old bytecode libraries, reflective access to JDK internals, the removed Security Manager, and new warnings about sun.misc.Unsafe and JNI.

  • Annotation processing is off by default since JDK 23. If Lombok, MapStruct, or a similar processor is on the plain classpath and not declared as a processor, javac now skips it. Nicolai Parlog’s write-up explains it well. The fix is to declare the processor path explicitly or pass -proc:full.
  • Bytecode-heavy libraries (Byte Buddy, ASM, Mockito, Lombok, Jacoco, older Hibernate) need versions that understand Java 25 class files. Upgrade these first. They cause most of the failures.
  • The Security Manager is permanently disabled (JDK 24). Code that calls System.setSecurityManager will throw an exception.
  • Warnings for sun.misc.Unsafe memory access (JDK 24) and restricted JNI use show up at runtime. They’re warnings for now, but they tell you which dependencies will break later.
  • Dynamically loaded agents print warnings (since JDK 21). Mockito’s inline mock maker is the classic case. Add the agent explicitly with -javaagent in your test configuration.
  • UTF-8 is the default charset (since JDK 18). If you’re coming from 17 on Windows, file reading and writing that silently relied on the platform encoding (often windows-1252) can now produce different results.
  • The 32-bit x86 port is gone. It’s rare these days, but check old build agents.

What is the step-by-step upgrade checklist for Java 25?

Update the build tooling first, then dependencies, then compile and test on 25, then roll out runtimes and containers. Turn on the new JVM features only after the app runs cleanly.

  1. Install a JDK 25 build next to your current one and confirm it:
    java -version
    javac -version
  2. Update build tools. Gradle needs 9.1.0 or later to run on or target Java 25. In Maven, use a current maven-compiler-plugin and set the release:
    <properties>
      <maven.compiler.release>25</maven.compiler.release>
    </properties>

    For Gradle:

    java {
        toolchain { languageVersion = JavaLanguageVersion.of(25) }
    }
  3. Upgrade the framework and bytecode libraries. Get onto current releases of Spring Boot, Hibernate, Lombok, Mockito, Byte Buddy, Jackson, and your test and coverage tools before you change the JDK target. Spring Boot 4.0 (November 2025) keeps a Java 17 baseline and works with JDK 25.
  4. Scan for JDK-internal API use:
    jdeps --jdk-internals --multi-release 25 -cp "libs/*" app.jar
  5. Fix annotation processing (declare processor paths or add -proc:full), then compile and run the full test suite. Read the runtime warnings. Don’t just scroll past them.
  6. Update runtimes: container base images (for example eclipse-temurin:25-jre), CI images, and the JDK on any VMs or app servers.
  7. Load test, then tune. Compare GC logs and memory against the old JDK. Then try -XX:+UseCompactObjectHeaders and an AOT cache, one at a time.

What came after Java 25?

Java 26 shipped March 17, 2026, and Java 27 shipped September 15, 2026. Both are non-LTS feature releases. Java 27 is the current one, supported by Oracle until March 2027.

Java 26 had 10 JEPs, including HTTP/3 for the HTTP Client API, G1 throughput improvements, AOT object caching with any GC, removal of the Applet API, and “Prepare to Make Final Mean Final,” which warns when deep reflection changes final fields.

Java 27 had nine JEPs. The notable ones: G1 becomes the default collector in all environments, compact object headers are on by default, and TLS 1.3 gets post-quantum hybrid key exchange. Structured concurrency, primitive patterns, and lazy constants are still in preview.

The pattern is that features finalized in 26 and 27 will show up in the next LTS. On the two-year cadence that would be Java 29, in September 2027. Testing your build against 27 now is a cheap way to find out what that upgrade will involve.

Bottom line

Java 25 is a sound LTS. It has no single headline feature like virtual threads were in 21, but it’s full of things that make code cleaner and services cheaper to run. If you’re on 17, start the upgrade now. Premier Support is over, and the gap only gets wider. If you’re on 21, plan it calmly, and check which JDK distribution you’re actually running before the licensing question gets decided for you. Upgrade the build tools and bytecode libraries first, read the warnings, and switch on the memory and startup features once the app is running cleanly.

FAQ

Is Java 25 an LTS release?

Yes. Java 25 is an LTS release, generally available since September 16, 2025. Oracle offers Premier Support until September 2030 and Extended Support until September 2033.

Is Java 17 still supported?

Oracle’s Premier Support for Java 17 ended in September 2026. Extended Support runs to September 2029, and Eclipse Temurin plans updates until at least October 2027.

Is Java 27 an LTS release?

No. Java 27, released September 15, 2026, is a six-month feature release, supported by Oracle until March 2027. Java 25 is the current LTS.

Is Oracle JDK 25 free to use?

Oracle JDK 25 updates are free under the No-Fee Terms and Conditions license through September 2028. OpenJDK builds such as Eclipse Temurin are free with no such cut-off.

Does Spring Boot work with Java 25?

Yes. Spring Boot 4.0, released in November 2025, keeps a Java 17 baseline and supports JDK 25. Use a current Spring Boot release when you upgrade the JDK.

Are compact object headers enabled by default in Java 25?

No. In Java 25 you enable them with -XX:+UseCompactObjectHeaders. They became the default in Java 27.

Featured image: Photo by Daniil Komov on Unsplash.

About The Author

Gene Fischer

Gene Fischer is a senior software engineer with more than 20 years of experience building software at large enterprise companies, working across both the Microsoft .NET and Java stacks. Now independent, he builds his own software products under Fischost Solutions, runs his own Windows Server and IIS hosting for his sites and apps, and teaches programming on his YouTube channel, codingwitheugene. He writes Computer Software Today to explain the tools working developers actually use, without the hype.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.