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:

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.
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).
456: Unnamed Variables & Patterns 458: Launch Multi-File Source-Code Programs 511: Module Import Declarations 512: Compact Source Files and Instance Main Methods
491: Synchronize Virtual Threads without Pinning 506: Scoped Values
454: Foreign Function & Memory API 467: Markdown Documentation Comments 484: Class-File API 485: Stream Gatherers 513: Flexible Constructor Bodies
483: Ahead-of-Time Class Loading & Linking 514: Ahead-of-Time Command-Line Ergonomics 515: Ahead-of-Time Method Profiling
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
493: Linking Run-Time Images without JMODs 518: JFR Cooperative Sampling 519: Compact Object Headers 520: JFR Method Timing & Tracing
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
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
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 😐
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.
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.
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.