We’re excited to announce that the Microsoft Build of OpenJDK binaries are now available for Java 25. As always, our builds aim to provide a high-quality, production-ready build of OpenJDK, with binaries tested across platforms (Windows, Linux, macOS) and backed by our support and release pipelines. With this release, we invite developers, teams, and organizations to start migrating to Java 25, and in doing so, to take advantage of the many enhancements that have accumulated since Microsoft Build of OpenJDK 21 (our previous LTS release).
Microsoft Build of OpenJDK 25 is fully supported for deployment on Azure Container Apps, Azure App Service, Azure Functions, and Azure Kubernetes Service, with up to date container images, so teams can modernize confidently for cloud-native hosting on Azure. Services with language runtimes managed by Microsoft will roll out JDK 25 binaries sometime in late October.
In this post, we will walk through the highlights of what’s new in Java 25, with short examples to quickly understand the changes. For a canonical list of JEPs (JDK Enhancement Proposals) since OpenJDK 21, see this official OpenJDK page.
What’s New in Java 25
These are the enhancements in Java 25 that are production-ready. Below are the (non exhaustive) highlights along with usage examples.
1. Compact Source Files & Instance Main Methods (JEP 512)
This feature makes Java lighter and more approachable for scripts, demos, small utilities, and even for education. You can now write a source file without a class declaration and use an instance main method instead of static. And you can simply run with “$ java Hello.java“.
Plus, these files get automatic imports of all classes on the java.base module.
2. Flexible Constructor Bodies (JEP 513)
Previously, Java required that any constructor must start by calling super(…) or this(…). With JEP 513, you can now execute validation or setup logic before the invocation of the superclass constructor, making it easier to centralize argument checks or shared initialization. Notice that the validation happens before the super(…) call, making the code cleaner and avoids duplication of parameter-checking logic across different constructors.