Blog
navigate_next
Java
What’s Brewing in JDK 24
Gaurav Sharma
December 18, 2024

Inside Java 24 (JDK 24): Comprehensive Guide to New Features and Improvements

As of 6th December, 2024, JDK 24 is considering a total of 24 JEPs. While this is a significant number for a 6-month release cycle, it remains to be seen how many will make it to the final release. Oracle has scheduled the official release of JDK 24 for March 18, 2025, continuing its consistent 6-month cadence for JDK versions.

Among the notable features under consideration are the Class File API, Stream Gatherers, ZGC with default generational mode, and Flexible Constructor Bodies. These exciting features have a strong likelihood of becoming part of JDK 25, the next Long-Term Support (LTS) version.

On the other hand, the much-anticipated String Templates feature has been removed from consideration for JDK 24. Its absence leaves developers wondering when it will return to the roadmap, as it was expected to be a game-changer for simplifying dynamic string composition.

Section1: Language and API Changes:

JEP 483: Ahead-of-Time Class Loading & Linking

When a Java application starts, it needs to do a lot of preparatory work: loading classes from files, linking them together, and setting up everything before the actual program can run.

This setup time is called "startup time," and for big applications, it can take several seconds or even minutes.

The intriguing thing is that most applications do almost the same setup work every time they start. JEP 483 takes advantage of this pattern by introducing a new feature: it watches what classes your application loads during one run, saves this information in a special cache file, and then uses this cache in future runs to start the application faster.

It works in three phases:

  1. First Run (Training): Java watches and records what your application does during startup
  2. Create Cache: Java creates a special cache file containing all the necessary class information
  3. Future Runs: Java uses this cache file to start your application much faster

JEP 484: Class-File API (Finalized)

Official Note: The Class-File API was originally proposed as a preview feature by JEP 457 in JDK 22 and refined by JEP 466 in JDK 23. We here propose to finalize the API in JDK 24 with minor changes, detailed below, based on further experience and feedback.

This API provides a standard way to work with Java class files - parsing, generating, and transforming them.

Until now, Java developers have relied on various third-party libraries (like ASM, BCEL, or Javassist) for bytecode manipulation. Even the JDK itself uses ASM internally. However, this dependency on external libraries creates several challenges:

  1. With Java's six-month release cycle, these libraries need frequent updates to support new Java features
  2. Each library has its own unique API, requiring developers to learn different approaches
  3. The JDK team has to maintain their own fork of ASM, adding to maintenance overhead

The Class-File API addresses these issues by providing a standardized, built-in solution that evolves alongside Java itself. This means developers can now work with class files using an official API that's guaranteed to support the latest Java features, reducing dependency on third-party libraries.

For those interested, we have covered this JEP in more detail in a separate article:
Link: Unlogged blog- Classfile API: Not your everyday Java API

JEP 488: Primitive Types in Patterns, instanceof, and switch (Second Preview)

JEP 488 moves into its second preview in Java 24, refining how Java handles primitive types in pattern matching contexts. This feature, which started with JEP 455 in JDK 23, remains unchanged but continues to gather developer feedback.

The JEP addresses long-standing limitations in Java's type system by extending pattern matching support to primitive types across <span class="pink">instanceof</span>, <span class="pink">switch</span>, and record patterns. Now, developers can directly check if a value can be safely converted between primitive types without manual range checks or explicit casting.

Perhaps the most significant improvement is the expansion of <span class="pink">switch</span> statements to support all primitive types including <span class="pink">long</span>, <span class="pink">float</span>, <span class="pink">double</span>, and <span class="pink">boolean</span>. This eliminates common workarounds previously needed when working with these types. The feature also enhances record patterns, making type conversions safer by automatically ensuring no data is lost during conversion.

For those interested, we have covered this JEP in more detail in our JDK 23 article:
Link: JDK 23: What to expect?

JEP 492: Flexible Constructor Bodies (Third Preview)

Official Note: This feature first previewed in JDK 22 via JEP 447, under a different title. It previewed for a second time in JDK 23 via JEP 482. We here propose to preview it for a third time, without significant change.

In older versions of Java, when writing a constructor, you had to call your parent class's constructor (<span class="pink">super()</span>) right at the start - before doing anything else. This was often frustrating because sometimes you need to check or prepare things first.

The new feature makes constructors more flexible by letting them work in two steps. First, you can now write code before calling <span class="pink">super()</span>. During this first step, you can validate values, prepare data, or set up basic object properties. There are some restrictions though - you can't use <span class="pink">this</span> or access parent class methods at this point. After calling <span class="pink">super()</span>, everything works just like before, with full access to all object features.

It was earlier known as "Statements Before Super" in JDK 22. The feature remains essentially the same but was renamed to "Flexible Constructor Bodies" in JDK 23.

For those interested, we have covered this JEP in more detail in our previous articles:

JEP 495: Simple Source Files and Instance Main Methods (Fourth Preview)

JEP 495 makes writing simple Java programs much easier, especially for beginners. This feature, now in its fourth preview in Java 24, simplifies basic Java programming.

This JEP hasn't changed since its previous version (JEP 477: Implicitly Declared Classes and Instance Main Methods), except for its title. The feature was first introduced in JDK 21 (JEP 445) and evolved through JDK 22 (JEP 463) and JDK 23 (JEP 477).

With this JEP, you no longer need to write class declarations for simple programs, and the main method can be written without <span class="pink">public static</span> or <span class="pink">String[]</span> args. Common utilities like <span class="pink">println</span> and basic Java APIs are automatically available without explicit imports. This makes Java more approachable for beginners while maintaining its power for advanced development.

For those interested, we have covered this JEP in more detail in our JDK 23 article:
JDK 23 coverage: JDK 23: What to expect?

JEP 485: Stream Gatherers (Finalized)

JEP 485 finalizes Stream Gatherers in Java 24, a feature designed to make stream operations more flexible and expressive. This feature was first previewed in JDK 22 (JEP 461) and continued in JDK 23 (JEP 473) without changes.

Stream Gatherers introduce <span class="pink">Stream::gather(Gatherer)</span>, a new intermediate stream operation that allows custom transformations of stream elements. Similar to how the Collectors API provides a generic way to define terminal operations through <span class="pink">Stream::collect(Collector)</span>, the Gatherer API offers a standardized approach for creating intermediate operations.

The design heavily borrows from the Collectors API pattern, but with key differences to support intermediate operations:

  • Uses an Integrator instead of BiConsumer for element processing
  • Employs BiConsumer for its finisher rather than Function
  • Allows one-to-one, one-to-many, many-to-one, or many-to-many transformations
  • Supports both finite and infinite streams
We have provided a more detailed explanation of Stream Gatherers in our JDK 23 article.
Link: JDK 23: What to expect?

JEP 494: Module Import Declarations (Second Preview)

This JEP introduces a new way to import Java packages that makes coding simpler, especially for beginners. Currently, when you want to use different Java features, you need to write multiple import statements at the top of your file (like <span class="pink">import java.util.*</span>, <span class="pink">import java.io.*</span>, etc.).

The new feature lets you import everything from a module using just one line: <span class="pink">import module java.base</span>. This is much simpler than writing many separate import statements. For example, instead of importing multiple packages separately to use Lists, Maps, and Streams, you can just import the entire module at once.

The main benefits are:

  1. Less code to write at the top of your files
  2. Easier for beginners to use Java features without knowing exactly where everything is located
  3. Simpler way to use third-party libraries
  4. You don't need to learn about Java modules to use this feature
There is one potential downside: if different packages have classes with the same name, you might need to specify exactly which one you want to use. But this can be easily fixed by adding a specific import statement for just that class.

JEP 499: Structured Concurrency (Fourth Preview)

Structured Concurrency enters its fourth preview in Java 24. While still a preview feature, it's been around since JDK 19 through JEP 428, helping developers manage concurrent operations better through <span class="pink">StructuredTaskScope</span>.

official note:

It re-previewed in JDK 22 via JEP 462, and JDK 23 via JEP 480, without change.

We here propose to re-preview the API once more in JDK 24, without change, to give more time for feedback from real world usage.

Most Java developers have dealt with <span class="pink">ExecutorService</span> for handling concurrent tasks. While it works, managing errors, cancellations, and task lifecycles can get messy. <span class="pink">StructuredTaskScope</span> tackles these pain points by organizing related concurrent tasks together - if one fails, you can automatically cancel the others, and you always know when and how tasks complete.

Key Benefits:

  1. Better error handling - When one task fails, others can be automatically cancelled
  2. Improved task management - All related concurrent tasks are treated as one unit
  3. Enhanced cleanup - Tasks are properly closed or cancelled when no longer needed
  4. Better monitoring - Makes it easier to track and debug concurrent operations

This extra preview phase gives the community more time to test it in real applications and provide feedback before it becomes permanent.

Section2: Performance Improvements/Deprecations and Removals:

JEP 498: Warn upon Use of Memory-Access Methods in sun.misc.Unsafe (Finalized)

This JEP introduces a warning system for developers who are using certain unsafe memory-access methods in Java's <span class="pink">sun.misc.Unsafe</span> class. These methods, which have been around since 2002, were originally intended for internal JDK use only but ended up being widely used by library developers for performance reasons.

Starting in JDK 24, developers will receive a warning the first time their code uses any of these unsafe memory methods. This warning will help identify which libraries are using these potentially dangerous methods.

Why this matters:

  • These methods can cause crashes and undefined behavior if not used carefully.
  • There are now safer, official alternatives available:
    • VarHandle API (since JDK 9) for handling on-heap memory
    • Foreign Function & Memory API (since JDK 22) for off-heap memory

The timeline:

  • JDK 23: These methods were marked as obsolete.
  • JDK 24: Will show a warning on first use
  • JDK 26 or later: Will throw an exception when these methods are used.
  • After JDK 26, we will completely remove the methods.

The main goal is to encourage developers to move away from these unsafe methods and adopt the newer, safer alternatives, making Java applications more stable and secure in the long run.

We have written a detailed blog on the upgrade, which is the FFM API:
Link: Foreign function and memory API - Java 22

JEP 490: ZGC: Remove the Non-Generational Mode (Finalized)

JDK 24 is removing ZGC's non-generational mode, making the generational version the only option going forward as part of Oracle's effort to reduce maintenance costs. Oracle decided this based on the strong performance of generational ZGC and the need to streamline development efforts.

The change means ZGC will exclusively run in generational mode, regardless of how developers configure it.

While the <span class="pink">-XX:ZGenerational</span> flag will still be accepted temporarily, it's now marked as obsolete and will be removed in a future release.

For most developers, this transition will be seamless. However, teams that optimized their applications specifically for non-generational ZGC might need to adjust their configurations.

This update means applications may see differences in performance, logging, or monitoring data, especially if they relied on the old mode. While most workloads will adapt without issues, some may need configuration adjustments.

We have covered the Z Garbage Collector and its different modes in our JDK 23 article (JEP 474).
Check out our detailed coverage here: JDK 23: What to expect?

JEP 479: Remove the Windows 32-bit x86 Port

This JEP is about removing support for running Java on 32-bit Windows computers.

Why is this happening?

  1. 32-bit Windows is becoming outdated
  2. Windows 10 (the last Windows that supports 32-bit) will stop being supported in October 2025
  3. New Java features don't work well on 32-bit Windows
  4. Removing 32-bit support will help Java developers focus on making new features better

What does this mean for users?

  • If you're using Java on a 32-bit Windows computer, you'll need to either:
    1. Switch to a 64-bit Windows computer
    2. Keep using an older version of Java (before Java 23) that still supports 32-bit Windows

Important points:

  • This only affects Windows computers
  • This doesn't affect other 32-bit systems (like Linux)
  • This doesn't affect older versions of Java that already support 32-bit Windows

purpose: to help Java move forward by removing support for outdated technology that very few people still use.

JEP 501: Deprecate the 32-bit x86 Port for Removal

This JEP is about stopping support for 32-bit x86 computers (mainly Linux systems). Java plans to mark this as "deprecated," which is basically a warning that this support will be completely removed in a future version (likely in Java 25).

The main reasons for this decision are:

  1. Very few people use 32-bit computers anymore - most have moved to 64-bit
  2. It's becoming too difficult to make new Java features work well on 32-bit systems
  3. Even Linux distributions like Debian are planning to stop supporting 32-bit systems
  4. The effort required to maintain 32-bit support could be better spent on developing new features

For users, this means:

  • If you're running Java on a 32-bit Linux computer, you'll need to either:
    1. Upgrade to a 64-bit system
    2. Keep using an older version of Java that still supports 32-bit
    3. Use something called the "Zero port" (a basic version that will still work on 32-bit systems)

This change shows how the computing world is moving away from older 32-bit technology to focus on modern 64-bit systems that can handle more advanced features.

JEP 472: Prepare to Restrict the Use of JNI

JNI (Java Native Interface) lets Java code work with non-Java code (typically C code). However, using JNI is risky for several reasons:

  1. It can crash Java programs unexpectedly
  2. It can cause memory problems
  3. It can bypass Java's security checks
  4. It can interfere with Java's garbage collection

This JEP is about preparing to make JNI usage more restricted. The main goal is to make Java secure by default, which means developers will need to explicitly approve the use of JNI in their applications.

<span class="pink">Java 22 introduced a safer alternative called the Foreign Function & Memory API</span>. This new API already requires developers to opt-in to use its risky features. JNI will follow the same approach.

This change is part of Java's larger effort to improve platform security and reliability by requiring explicit permissions for potentially dangerous features. This includes other changes like removing unsafe memory access methods and restricting dynamic agent loading.

The end result will be a more secure and stable Java platform where potentially risky features need explicit approval to be used.

We have provided an in-depth analysis of the Foreign Function & Memory API in our previous article: JDK 23: What to expect?

JEP 475: Late Barrier Expansion for G1

JEP 475 improves how Java's G1 garbage collector works with the Java compiler (C2). The goal is to make Java applications run more efficiently, especially in cloud environments.

The G1 garbage collector needs to track memory changes when Java programs create or modify objects. It uses "barriers" (monitoring code) to do this tracking. Currently, these barriers are added very early in the compilation process.

This current approach causes several problems:

  • Slows down the compilation process by 10-20%
  • Makes the code unnecessarily complex and difficult to understand
  • Can create bugs because of timing issues with these barriers

JEP 475 solves these issues by moving when barriers are added—from the beginning to the end of the compilation process. This change makes the compilation faster, the code simpler, and helps prevent timing-related bugs.

This improvement is especially helpful when running Java applications in the cloud.  This approach works well because it's already being used successfully in another part of Java (ZGC) since JDK 14

JEP 486: Permanently Disable the Security Manager

JD 24 is permanently disabling the Security Manager, an old feature from the 1990s that helped protect computers from harmful Java code by controlling access to files and networks. The change is happening because almost no one uses Security Manager anymore (it was always off by default), and it makes Java harder to maintain. Modern security tools like containers do a better job now.

Starting with JDK 24, you won't be able to enable Security Manager at all - trying to do so will just give you an error. This won't affect most developers since they weren't using it anyway. Only a small number of older applications that still use Security Manager will need updates. If you're using Java 17 or earlier, you won't see any changes. For those few applications that do use Security Manager, you'll need to check your command line settings and consider switching to modern security alternatives.

JEP 404: Generational Shenandoah (Experimental)

JDK 24 brings an experimental upgrade to the Shenandoah garbage collector by introducing generational collection capabilities. This enhancement splits memory management into two spaces: young generation for new objects and old generation for long-lived ones.

While maintaining Shenandoah's low-pause times, this approach delivers better memory utilization, reduced CPU overhead, and improved handling of allocation spikes.

Though optional and activated via command line flags, most applications should benefit from this more efficient collection strategy.

To enable this experimental feature, use the following command:

java -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=generational

JEP 491: Synchronize Virtual Threads without Pinning

JDK 24 is trying to solve a major performance issue with virtual threads. Previously, when virtual threads used synchronized blocks they would get stuck to their underlying system threads, limiting how many tasks could run simultaneously. Now, virtual threads can temporarily release these system threads when waiting for operations to complete, even inside synchronized blocks.

This means your existing Java applications can handle more concurrent tasks efficiently without needing any code changes. Upgrading to JDK 24 automatically enhances your applications' performance, particularly under high load.

Section 3: Cryptographic JEPs for  the Future

JDK 24 includes three cryptographic JEPs for the future. To prepare for the future where quantum computers could break encryption algorithms like RSA and Diffie-Hellman, Java is adopting quantum-resisting alternatives. These module-based lattice algorithms are standardized by the United States Institute of Standards and Technology. and JDK 24 enables them for key encapsulations and digital signatures.

JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism (Finalized)

JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm (Finalized)

JEP 478: Key Derivation Function API (Preview)

A comprehensive review of these JEPs will be presented as more details emerge.

Final Note:

Although there is still time for the features to be finalized for JDK 24, it's good to see certain dedicated cryptographic JEPs and the removal of certain old features. Personally, I feel like Java is bound to make a huge comeback in LTS JDK 25 despite all the unnecessary hate in the community.

References:

Gaurav Sharma
December 17, 2024
Use Unlogged to
mock instantly
record and replay methods
mock instantly
Install Plugin