Java 25: The Nice, the Meh, and ...

When a new “long term support” release of Java comes out, I like to reflect on what improvements that it brings are nice, meh, ugly, or otherwise remarkable. Now we have Java 25, and here are my totally unbiased opinions.

Here are some links to check out, with more detail and perhaps less opinion:

LTS or Not?

.webp

In the Java release cadence, we have a new version every six months. Version 25 was released 2025-09-16, remarkably with perfect squares for the version number, year, month, and day. That won’t happen again for a good long time.

Some releases are specially blessed to receive long-term support from Oracle and/or other vendors, others are briefly gorgeous and soon forgotten with the rest.

Of course, as Nikolai Parlog reminds us, every release is as good as the next, and there are no rules about support levels. Nevertheless, his employer picks favorites, and Java 25 is one of them. And other vendors follow Oracle’s lead.

Whenever that happens, I find it worthwhile to reflect on the changes from the previous blessed release.

In 2021, I opined that records were nice, sealed classes were ok, file and stream API improvements were nice too, and switch enhancements were a hot mess. But you should upgrade. Because, bug fixes and security upgrades galore.

In 2023, I did the same and said you should upgrade, because of virtual threads, and maybe pattern matching improvements, and certainly because of bug fixes, and, security.

JEPs Since Java 21

Here are the Java Enhancement Proposals that made it into Java 22 to 25, sorted by theme, and excluding preview and experimental features (which you presumably won’t want to run in production).

Simplifying Java
456: Unnamed Variables & Patterns
458: Launch Multi-File Source-Code Programs
511: Module Import Declarations
512: Compact Source Files and Instance Main Methods
Concurrency
491: Synchronize Virtual Threads without Pinning
506: Scoped Values
Language, API, and Tools
454: Foreign Function & Memory API
467: Markdown Documentation Comments
484: Class-File API
485: Stream Gatherers
513: Flexible Constructor Bodies
Project Leyden
483: Ahead-of-Time Class Loading & Linking
514: Ahead-of-Time Command-Line Ergonomics
515: Ahead-of-Time Method Profiling
Garbage Collection
423: Region Pinning for G1
474: ZGC: Generational Mode by Default
475: Late Barrier Expansion for G1
490: ZGC: Remove the Non-Generational Mode
521: Generational Shenandoah
Other VM
493: Linking Run-Time Images without JMODs
518: JFR Cooperative Sampling
519: Compact Object Headers
520: JFR Method Timing & Tracing
Security
496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism
497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm
498: Warn upon Use of Memory-Access Methods in sun.misc.Unsafe
510: Key Derivation Function API
Deprecation/Removal
471: Deprecate the Memory-Access Methods in sun.misc.Unsafe for Removal
472: Prepare to Restrict the Use of JNI
479: Remove the Windows 32-bit x86 Port
486: Permanently Disable the Security Manager
501: Deprecate the 32-bit x86 Port for Removal
503: Remove the 32-bit x86 Port

Totally Unbiased Ratings

For me personally, the big changes are in the “Simplifying” category. Teaching Java has become quite a bit simpler, by removing cruft from the ages and introducing a consistent framework for getting started. More consistent, in fact, than Python. Anyone teaching programming should have another look. And Java has become a great choice for small coding tasks. My rating: Two enthusiastic thumbs up 👍👍

But of course, that isn’t why most people use Java. When Java 21 was released, I said that virtual threads are a momentous sea change. No more tedious reactive code. That is where JEP 491 comes in. It resolves a substantial impedimemt for using virtual threads in production. Scoped values, on the other hand, lay important groundwork, but until a framework that you use uses them, you probably aren’t impacted. My rating: One enthusiastic thumb up 👍

As for “Language, API, and Tools”, the Foreign Function and Memory API is a potential game changer if lots of library writers embrace it; for example, to interface to AI libraries. Gatherers are a genuine improvement if you use streams. You probably won’t be using the class file API directly, but it is a good thing for tool builders. Flexible constructor bodies are important plumbing, but also not something that impacts most programmers. I am meh about Markdown, but I can see how it can be a better match for JavaDoc than HTML. Overall, I rate this category as cool 😎

Java is not known for starting fast. Quarkus and others offer an option to compile to native code with GraalVM, but there are limitations. Oracle instead banks on Project Leyden to achieve the same goals, and Java 25 lays some groundwork. I’ll have to dig into the details to understand their value. If your framework of choice starts using them, that’s a good sign. For now, my rating is optimistic 🌈

I don’t know enough about the finer points of garbage collection, VM internals, or security, to form a professional opinion, but I am glad that the Java team does, so I’ll simply rate them as attaboy ✔️

Should one rate deprecations? They are useful in the grand scheme of things, but you wouldn’t upgrade for them. Here is U+1F610, or as we say in Java, \uD83D\uDE10, a neutral face 😐

API Changes

The awesome Java Almanac site shows the difference between any two Java releases, so let us check out what changed between Java 21 and 25.

With some release updates, one can find a good number of nuggets, but this time, not so much. You can now call Path.resolve with any number of paths. You can get a stream of available currencies. Other than the new IO class, there isn’t much new.

Should You Upgrade?

I did in a jiffy, but I am biased because of my “Java for small programming tasks” use case. If you use, or intend to use, virtual threads, you should also take the plunge. If a framework that you use takes advantage of Project Leyden AOT speedups, go for it. Also if the GC changes are meaningful to you. And of course, as always, there is a large number of fixes for bugs and security risks that you miss at your peril. If you have made it past Java 8, and you are not impacted by one of the deprecations, it is easy to do. Which is a huge strength of Java.

Comments

With a Mastodon account (or any account on the fediverse), please visit this link to add a comment.

Thanks to Carl Schwann for the code for loading the comments.

Not on the fediverse yet? Comment below with Talkyard.