Martin Ahrer

Thinking outside the box

Java 24 major language and API improvements

2025-08-27 8 min read Martin

Java ㉔ has been released in March 2025.

The following content is summarizing the most important changes to the Java API, the Java language, and the JVM introduced with Java Java ㉔.

For a more complete overview, follow the links in the following sections referring to the official Oracle release documents.

Java 24 Language improvements

The following describes selected improvements of the Java language. See the Java 24 release notes. See Java Language Updates for Java SE 24.

Java 24 is introducing the following language enhancements as developer preview.

  • JEP 488 is continuing with Primitive Types in Patterns, instanceof, and switch (Second Preview). Enhance pattern matching by allowing primitive type patterns in all pattern contexts, and extend instanceof and switch to work with all primitive types.

  • JEP 492 is continuing with Flexible Constructor Bodies (Third Preview). In constructors in the Java programming language, allow statements that do not reference the instance being created to appear before an explicit constructor invocation.

  • JEP 494 is continuing with Module Import Declarations (Second Preview). Enhance the Java programming language with the ability to succinctly import all of the packages exported by a module. This simplifies the reuse of modular libraries, but does not require the importing code to be in a module itself.

  • JEP 495 is continuing with Simple Source Files and Instance Main Methods (Fourth Preview). Enhance the Java programming language so that students can write their first programs without needing to understand language features designed for large programs.

We are not diving into the details of these preview features and defer that until they are moving from preview for general availability.

Java 24 API improvements

The following describes selected improvements of the Java API. See the Java 24 release notes.

Java 24 is introducing the following finalized API enhancements.

  • JEP 484 is finalizing the Class-File API. Provide a standard API for parsing, generating, and transforming Java class files. This API will replace the need for third-party libraries like ASM.

  • JEP 485 is finalizing Stream Gatherers. Enhance the Stream API to support custom intermediate operations. This will allow stream pipelines to transform data in ways that are not easily achievable with the existing built-in intermediate operations.

  • JEP 496 is introducing Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism. Provide implementations of KEM based on the Module-Lattice-Based Key-Encapsulation Mechanism (ML-KEM) standard specified in FIPS 203.

  • JEP 497 is introducing Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm. Provide implementations of the Module-Lattice-Based Digital Signature Algorithm (ML-DSA) standard specified in FIPS 204.

Code samples are only available for selected JEPs!

Java 24 is continuing the following API enhancements as developer preview or incubator.

  • JEP 478 is starting with Key Derivation Function API (Preview). Provide an API for Key Derivation Functions (KDFs), which are cryptographic algorithms for deriving additional keys from a secret key or other high-entropy key material.

  • JEP 487 is continuing with Scoped Values (Fourth Preview). Enable the sharing of immutable data within and across threads. They are preferred to thread-local variables, especially when using large numbers of virtual threads.

  • JEP 489 is continuing with Vector API (Ninth Incubator). Introduce an API to express vector computations that reliably compile at runtime to optimal vector instructions on supported CPU architectures, thus achieving performance superior to equivalent scalar computations.

  • JEP 499 is continuing with Structured Concurrency (Fourth Preview). Simplify multithreaded programming by introducing an API for structured concurrency. Structured concurrency treats multiple tasks running in different threads as a single unit of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability.

We are not diving into the details of these preview features and defer that until they are moving from preview for general availability.

Class File Api

Before Java 24, working with Java class files required third-party libraries like ASM or BCEL. The new Class-File API provides a standard way to parse, generate, and transform Java class files.

Parse Class File
Path classPath = Path.of("build/classes/java/main/twentyfour/api/ClassFileApi.class");

byte[] classBytes = Files.readAllBytes(classPath);
ClassModel classModel = ClassFile.of().parse(classBytes);

System.out.println("Class name: " + classModel.thisClass().asInternalName());
System.out.println("Method count: " + classModel.methods().size());

classModel.methods().forEach(method ->
    System.out.println("Method: " + method.methodName().stringValue())
);
Generate Class File
ClassDesc helloWorldClass = ClassDesc.of("HelloWorld");

byte[] classBytes = ClassFile.of()
    .build(helloWorldClass, classBuilder -> {
      classBuilder
          .withFlags(ACC_PUBLIC)
          .withMethod("main", MethodTypeDesc.of(CD_void, CD_String.arrayType()),
              ACC_PUBLIC | ACC_STATIC, methodBuilder -> {
                methodBuilder.withCode(codeBuilder -> {
                  codeBuilder
                      .getstatic(ClassDesc.of("java.lang.System"), "out",
                          ClassDesc.of("java.io.PrintStream"))
                      .ldc("Hello from generated class!")
                      .invokevirtual(ClassDesc.of("java.io.PrintStream"), "println",
                          MethodTypeDesc.of(CD_void, CD_String))
                      .return_();
                });
              });
    });
Files.write(Path.of("HelloWorld.class"), classBytes);

The Class-File API allows programmatic generation of class files without external dependencies. This example creates a simple "Hello World" class dynamically.

Transform Class File
Path classPath = Path.of("build/classes/java/main/twentyfour/api/ClassFileApi.class");
byte[] originalBytes = Files.readAllBytes(classPath);

byte[] transformedBytes = ClassFile.of().transformClass(
    ClassFile.of().parse(originalBytes),
    ClassTransform.transformingMethods(
        (methodBuilder, methodElement) -> {
          if (methodElement instanceof CodeAttribute codeAttr) {
            methodBuilder.transformCode(codeAttr,
                CodeTransform.ofStateful(() ->
                    (builder, element) -> {
                      builder.with(element);// pass through
                    })
            );
          } else {
            methodBuilder.with(methodElement);
          }
        }
    )
);
Files.write(Path.of("build/tmp/TransformedClass.class"), transformedBytes);

The API also supports transforming existing class files, such as adding logging or modifying method behavior.

Stream Gatherers

Before Java 24, creating sliding windows required complex collectors or external loops.

Sliding Window Before Java24
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);

List<List<Integer>> pairs = new ArrayList<>();
for (int i = 0; i < numbers.size() - 1; i++) {
    pairs.add(List.of(numbers.get(i), numbers.get(i + 1)));
}

assertEquals(5, pairs.size());
assertEquals(List.of(1, 2), pairs.get(0));
assertEquals(List.of(2, 3), pairs.get(1));
Sliding Window With Java24
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);

List<List<Integer>> pairs = numbers.stream()
    .gather(Gatherers.windowSliding(2))
    .toList();

assertEquals(5, pairs.size()); // [1,2], [2,3], [3,4], [4,5], [5,6]
assertEquals(List.of(1, 2), pairs.get(0));
assertEquals(List.of(2, 3), pairs.get(1));

Java 24 Stream Gatherers provide built-in sliding window operations as intermediate operations.

Before Java 24, creating batched processing required complex collectors or multiple stream operations.

Batch Processing Before Java24
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

List<Integer> batchSums = new ArrayList<>();
List<Integer> currentBatch = new ArrayList<>();

for (Integer number : numbers) {
    currentBatch.add(number);
    if (currentBatch.size() == 3) {
        int sum = currentBatch.stream().mapToInt(Integer::intValue).sum();
        batchSums.add(sum);
        currentBatch.clear();
    }
}
if (!currentBatch.isEmpty()) {
    int sum = currentBatch.stream().mapToInt(Integer::intValue).sum();
    batchSums.add(sum);
}

assertEquals(List.of(6, 15, 24, 10), batchSums); // (1+2+3), (4+5+6), (7+8+9), (10)
Batch Processing With Java24
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

List<Integer> batchSums = numbers.stream()
    .gather(Gatherers.windowFixed(3))
    .map(batch -> batch.stream().mapToInt(Integer::intValue).sum())
    .toList();

assertEquals(List.of(6, 15, 24, 10), batchSums); // (1+2+3), (4+5+6), (7+8+9), (10)

Java 24 gatherers make batch processing simple with custom intermediate operations.

Before Java 24, creating running totals required external state or complex collectors.

Running Total Before Java24
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

List<Integer> runningSums = new ArrayList<>();
int runningTotal = 0;

for (Integer number : numbers) {
    runningTotal += number;
    runningSums.add(runningTotal);
}

assertEquals(List.of(1, 3, 6, 10, 15, 21, 28, 36, 45, 55), runningSums);
Running Total With Java24
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

Gatherer<Integer, ?, Integer> runningSum = Gatherer.ofSequential(
    () -> new int[]{0}, // state: running total
    Gatherer.Integrator.ofGreedy((state, element, downstream) -> {
        state[0] += element;
        downstream.push(state[0]);
        return true;
    })
);

List<Integer> runningSums = numbers.stream()
    .gather(runningSum)
    .toList();

assertEquals(List.of(1, 3, 6, 10, 15, 21, 28, 36, 45, 55), runningSums);

Java 24 gatherers can maintain state for complex transformations like running totals.

Before Java 24, flattening and filtering required multiple stream operations or complex collectors.

Flatten And Filter Before Java24
List<String> sentences = List.of(
    "Java 24 is great",
    "Stream gatherers are useful",
    "Programming is fun"
);

List<String> longWords = sentences.stream()
    .flatMap(sentence -> List.of(sentence.split(" ")).stream())
    .filter(word -> word.length() > 4)
    .toList();

assertEquals(List.of("great", "Stream", "gatherers", "useful", "Programming"), longWords);
Flatten And Filter With Java24
        List<String> sentences = List.of(
            "Java 24 is great",
            "Stream gatherers are useful",
            "Programming is fun"
        );

        Gatherer<String, ?, String> splitWords = Gatherer.ofSequential(
            Gatherer.Integrator.ofGreedy((unused, sentence, downstream) -> {
                for (String word : sentence.split(" ")) {
                    downstream.push(word);
                }
                return true;
            })
        );
        
        List<String> longWords = sentences.stream()
            .gather(splitWords)
            .filter(word -> word.length() > 4)
            .toList();

        assertEquals(List.of("great", "Stream", "gatherers", "useful", "Programming"), longWords);
    }
}

Java 24 gatherers can be chained together for complex transformations in a single pipeline.

Java 24 JVM improvements

The following describes selected improvements of the Java Virtual Machine. See the Java 24 release notes.

Java 24 is introducing the following finalized JVM enhancements.

  • JEP 475 is introducing Late Barrier Expansion for G1. Improve G1 garbage collector performance by moving the expansion of GC barriers from the platform-independent optimization phase to the platform-dependent code generation phase.

  • JEP 490 is ZGC: Remove the Non-Generational Mode. Remove ZGC’s non-generational mode, retaining only the generational mode, which offers better application performance.

  • JEP 491 is introducing Synchronize Virtual Threads without Pinning. Enable virtual threads to synchronize without pinning the underlying platform thread by reimplementing object monitors to use a new locking scheme.

Java 24 is introducing the following experimental JVM enhancements.

  • JEP 404 is starting with Generational Shenandoah (Experimental). Improve application performance by extending Shenandoah to maintain separate generations for young and old objects, allowing more frequent collection of short-lived objects.

  • JEP 450 is starting with Compact Object Headers (Experimental). Reduce the memory footprint of Java objects by implementing compact object headers.

Java 24 Tooling and Platform improvements

The following describes selected improvements of the Java platform and tooling. See the Java 24 release notes.

Java 24 is introducing the following platform and tooling enhancements.

  • JEP 472 is Prepare to Restrict the Use of JNI. Prepare to restrict the use of JNI by issuing warnings when JNI is used by code on the class path. This prepares for a future release that will throw exceptions instead of issuing warnings.

  • JEP 479 is Remove the Windows 32-bit x86 Port. Remove the Windows 32-bit x86 port (windows-x86) from the JDK.

  • JEP 483 is introducing Ahead-of-Time Class Loading & Linking. Improve startup time and time to peak performance by enabling classes to be loaded and linked ahead of time.

  • JEP 486 is Permanently Disable the Security Manager. Permanently disable the Security Manager, which has been deprecated since Java 17 and marked for removal.

  • JEP 493 is introducing Linking Run-Time Images without JMODs. Enable jlink to create run-time images without requiring JMOD files to be present, provided that the packaged modules contain the same content.

  • JEP 498 is Warn upon Use of Memory-Access Methods in sun.misc.Unsafe. Issue warnings when memory-access methods in sun.misc.Unsafe are used. This prepares for their eventual removal or restriction.

  • JEP 501 is Deprecate the 32-bit x86 Port for Removal. Deprecate the 32-bit x86 port (linux-x86) with the intent to remove it in a future release.