Join our webinar 9/18 to be prepared for the release of JDK 25 
Support
Blog chevron_right Java

A Java Champion’s Guide to JDK 25 Features

A Java Champion’s Guide to JDK 25 Features

Summary 

JDK 25 is the newest LTS Java version and the first since JDK 21 in 2023. It includes 18 JDK Enhancement Proposals, including 14 closed, three previews, and one incubator.  

In this post you will learn: 

  • JEP 507 removes top-down restrictions on cases 
  • JEP 512 makes it easier to write your first Java application 
  • JEP 513 relaxes certain restrictions on how constructors must work 
  • JEP 505, which is in its fifth preview iteration as part of Project Loom, treats groups of related tasks running in different threads as single units of work 

It’s September again, and that means another release of the JDK under the six-month release cadence. This has been working really well, and we’ve seen a faster rate of change in Java than at any time in its 30-year history. As has been the case since JDK 9, the new features are defined using a set of JDK Enhancement Proposals (JEPs). JDK 25 is the first Long-Term Support (LTS) release since JDK 21 in 2023. 

A few random observations: 

  • JDK 25 is released in 2025 
  • JDK 24 had 24 JEPs 
  • JDK 25 contains 18 JEPs 
  • This is higher than the average of 13 and slightly more than the 15 in JDK 21 (the previous LTS release) 

Java language JEPs in JDK 25

As usual, many of the JEPs relate to features which are not yet final. These preview features (defined by JEP 12) and incubator modules (defined by JEP 11) enable fully developed features to be included in the JDK while still providing an opportunity for those features to be modified based on feedback. 

Let’s dive into this latest release, starting with things that are part of the Java language. 

JEP Name Status
507  Primitive Types in Patterns, instanceof, and switch  Preview 

JEP 507 delivers a third preview of Primitive Types in Patterns, instanceof, and switch. This feature was introduced in JDK 23 and has remained unchanged since. Although Java is an object-oriented language, it also supports primitive values (fundamental data types built directly into the language) to enable better performance. The problem is that certain parts of the language don’t allow primitives to be used, and so the equivalent wrapper classes must be substituted, with the necessary overhead of object creation and garbage collection. Project Valhalla will hopefully allow us to create generic types that can use primitives as the type parameter. For now, the difficulties are being reduced by allowing primitives to be used in Patterns. This is a significant improvement for switch in particular. However, some edge cases require additional consideration to fully understand. 

For example, look at this switch:

int x = 42; 


switch (x) { 

      int x -> System.out.println(“int”); 

      byte b -> System.out.println(“byte”); 

}

What would you expect to happen? 

The answer is (at least to me) a little surprising. 

This switch will cause a compiler error, as the int case dominates the byte one, making it unreachable.

switch (x) { 

      Integer x -> System.out.println(“int”); 

      byte b -> System.out.println(“byte”); 

}

In the second switch, the boxing conversion from int to Integer is unconditionally exact, so the compiler does not determine that there is still dominance. This will compile and run quite happily. 

Let’s look at the other features in JDK 25. 

JEP Name Status
511  Module Import Declarations  Closed, delivered 

JEP 511 is Module Import Declarations. A small change that simplifies the way you can import all of the publicly accessible elements of a module using a single statement. It’s similar to the way the import statement allows the use of a wildcard for package elements. 

JEP Name Status
512  Compact Source Files and Instance Main Methods  Closed, delivered 

JEP 512 is Compact Source Files and Instance Main Methods. This is now a final feature and is part of a longer-running attempt to reduce the difficulty in writing your very first Java application. Rather than requiring all of the code necessary to define a class with a main method qualified as public static void, the following is all you need:

void main() { 

    IO.println("Hello, World!"); 

}

JEP Name Status
513  Flexible Constructor Bodies  Closed, delivered 

JEP 513 is Flexible Constructor Bodies. This relaxes certain restrictions on how constructors must work. Previously, any call to the superclass or an overloaded constructor must have been the first statement. Now, certain things like tests on parameter values can be evaluated and potentially an exception thrown before that call. This reduces more complex code and eliminates unnecessary method calls. This was introduced as a preview feature in JDK 22 under JEP 447 called Flexible Constructor Bodies and is now final. 

Switching to the class libraries, we have the following features: 

JEP Name Status
470  PEM Encoding for Cryptographic Objects  Closed, delivered 

JEP 470 is PEM Encoding for Cryptographic Objects. This provides an API for encoding/decoding objects that represent cryptographic keys, certificates, and certificate revocation lists in and out of the widely used Privacy-Enhanced Mail (PEM) transport format. 

JEP Name Status
502  Stable Values  Preview 

JEP 502 is Stable Values. A big point of discussion in developing Java code is the best use of objects that hold immutable values. Java has always had the final keyword, but this is not truly final, since final fields can be modified through reflection. The Stable Values JEP introduces an API for objects that are treated as constants by the JVM, and so can benefit from the same performance benefits as final variables. In addition, Stable Values provide greater flexibility for when they are initialised. This is a preview feature. 

JEP Name Status
505  Structured Concurrency  Preview 

JEP 505 is Structured Concurrency and is now in its fifth preview iteration. As part of the wider Project Loom, Structured Concurrency treats groups of related tasks running in different threads as single units of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability. 

JEP Name Status
506  Scoped Values  Closed, delivered 

JEP 506 is Scoped Values. This is also part of Project Loom and related to Structured Concurrency. Scoped Values enable a method to share immutable data both with its callees within a thread and with child threads. Scoped values are designed to be a simpler alternative to thread-local variables. Having been introduced as a preview feature in JDK 21, the feature is now final. 

JEP Name Status
508  Vector API  Incubator 

JEP 508 is the Vector API, now in its record-breaking tenth incubator iteration. The Vector API is part of the larger Project Valhalla, which is why it remains an incubator API. Until other parts of Valhalla are delivered, this will not be finalised in case further changes are required. This API provides a way for developers to give the JVM explicit instructions about how to use Vector operations (single instruction multiple data) to allow multiple numerical operations (typically on an array) to be performed in a single clock cycle. The JIT compiler in the JVM is already capable of using autovectorization, but it is not always able to recognise situations where it can be applied. Alternative implementations, such as the Azul Falcon JIT compiler, part of Platform Prime, can autovectorize significantly more code, making this API less valuable. 

JEP Name Status
510  Key Derivation API  Closed, delivered 

JEP 510 is the Key Derivation API. This is an API for Key Derivation Functions (KDFs), which are cryptographic algorithms for deriving additional keys from a secret key and other data. Introduced as a preview feature in JDK 24, this is now final. 

JDK 25 also includes several features that are specific to the JVM and other parts of the JDK. 

JEP Name Status
519  Compact Object Headers  Closed, delivered 

JEP 519 is Compact Object Headers. On common 64-bit platforms, the JVM has used 128 bits to represent an object header that includes the address of the object in the heap and various status bits. This has now been reduced to 64 bits without loss of functionality. Although this may seem like a small change, it can have a significant impact. Profiling has shown a 22% reduction in heap size and 8% less CPU time on a common benchmark. This was introduced as a preview feature in JDK 24 and is now final. 

JEP Name Status
521  Generational Shenandoah  Closed, delivered 

JEP 521 is Generational Shenandoah. Shenandoah is an alternative garbage collection algorithm developed by Red Hat. Initially, using a non-generational heap did not deliver the necessary performance for many applications. Introduced as a preview feature in JDK 24, this is now final. Other algorithms, such as Azul’s C4, part of Platform Prime, can deliver even greater performance and reduced latency. 

Two JEPs are part of the larger project Leyden, which is intended to reduce the startup and warmup times associated with JVM applications. 

JEP Name Status
514  Ahead-of-Time Command-Line Ergonomics  Closed, delivered 

JEP 514 is Ahead-of-Time Command-Line Ergonomics. Ahead-of-Time Class Loading and Linking was included in JDK 24 but required a two-phase mechanism to generate and process profiling data. This has been improved to eliminate the need for a separate process phase. 

JEP Name Status
515  Ahead-of-Time Method Profiling  Closed, delivered 

JEP 515 is Ahead-of-Time Method Profiling. This builds on AOT Class Loading and Linking to provide method-execution profiling data when restarting an application. Alternatives, such as ReadyNow, which is already included in Azul’s Platform Prime, offer all of these features, as well as reusing compiled code from previous runs of an application. This can deliver significant performance gains. 

There are three JEPs related to the built-in profiling tool, Java Flight Recorder (JFR). 

JEP Name Status
509  JFR CPU-Time Profiling  Closed, delivered 

JEP 509, JFR CPU-Time Profiling, is introduced as an experimental feature. This captures more accurate CPU-time profiling information on Linux. 

JEP Name Status
518  JFR Cooperative Sampling  Closed, delivered 

JEP 518 is JFR Cooperative Sampling. This improves the stability of profiling data collection when Java thread stacks are sampled asynchronously. This is achieved by walking call stacks only at safepoints, while minimising safepoint bias. 

JEP Name Status
520  JFR Method & Tracing  Closed, delivered 

JEP 520 is JFR Method Timing & Tracing. This provides facilities for method timing and tracing via bytecode instrumentation. 

JEP Name Status
503  Remove the 32-bit x86 Port  Closed, delivered 

The final feature in JDK 25 is JEP 503, Remove the 32-bit x86 Port. The 32-bit Windows port of the JDK was removed in JDK 24, so this completes the work of eliminating all 32-bit ports. Although some people still use 32-bit operating systems, these are very old and would not be expected to upgrade their JDK without also upgrading the OS. 

As you can see, JDK 25 includes a wide variety of features that will make life easier for developers and users alike. JDK 25 is also a Long-Term Support (LTS) version for binary distributions, like Azul’s Platform Core. This means it will have extended maintenance (updates) and support. 

Why not give it a try? 

CTA