Wednesday, September 23, 2026

JDK-27: hard sell?

The JDK release train is so stable that many do not pay attention anymore! Nonetheless, the new JDK-27 release is there and quite a few things to unpack.

  • JEP 527: Post-Quantum Hybrid Key Exchange for TLS 1.3: enhances the security of Java applications that require secure network communication by implementing hybrid key exchange algorithms for TLS 1.3. Such algorithms defend against future quantum computing attacks by combining a quantum-resistant algorithm with a traditional algorithm. Applications that use the javax.net.ssl APIs will benefit from these improved algorithms by default, without change to existing code.

  • JEP 523: Make G1 the Default Garbage Collector in All Environments: makes the Garbage-First (G1) garbage collector the default collector in all environments, rather than just server environments. It worth noting that all other collectors are still available and could be specified, only default changes.

  • JEP 534: Compact Object Headers by Default: makes compact object headers the default object header layout in the HotSpot JVM. Compact object headers reduce object headers from 96 bits down to 64 bits on 64-bit architectures, thereby reducing heap size, improving deployment density, and increasing data locality.

  • JEP 536: JFR In-Process Data Redaction: enhances JDK Flight Recorder (JFR) to redact command-line arguments and the initial values of environment variables and system properties in recordings. Redact this data before it leaves the process, so that sensitive information does not leak.

    The new sub-options redact-key and redact-argument have been introduced, allowing to specify one or more filters that select the command-line arguments, environment variables, and system properties to be redacted.

      java -XX:FlightRecorderOptions:'redact-key=confidential,redact-argument=https://*:*@*' ...
      

Quite a few preview and incubating (vectors!) features have been carried over from the previous releases, notably:

  • JEP 538: PEM Encodings of Cryptographic Objects (Third Preview): introduces an API for encoding objects that represent cryptographic keys, certificates, and certificate revocation lists into the widely-used Privacy-Enhanced Mail (PEM) transport format, and for decoding from that format back into objects. This is a preview API feature.

  • JEP 532: Primitive Types in Patterns, instanceof, and switch (Fifth Preview): enhances pattern matching by allowing primitive types in all pattern contexts, and extend instanceof and switch to work with all primitive types. This is a preview language feature.

  • JEP 531: Lazy Constants (Third Preview): introduces an API for lazy constants, which are objects that hold unmodifiable data. Lazy constants are treated as true constants by the JVM, enabling the same performance optimizations that are enabled by declaring a field final. Compared to final fields, however, lazy constants offer greater flexibility as to the timing of their initialization. This is a preview API feature.

  • JEP 533: Structured Concurrency (Seventh Preview): simplifies concurrent programming by introducing an API for structured concurrency. 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. This is a preview API feature.

  • JEP 537: Vector API (12th Incubator): introduces an API to express vector computations that reliably compile at run time to optimal vector instructions on supported CPUs, thus achieving performance superior to equivalent scalar computations. This is an incubating API feature.

The standard library (to my surprise at least) got only a handful of changes and bug fixes introduced, the most interesting ones are below.

That was it. Let us take a look which changes went into JVM itself, including garbage collection:

Moving on to JDK and tooling, a number of highlights here:

The list of different security related fixes and enhancements is truly impressive:

By and large, JDK-27 is not the release that brings a lot to the table. Still, for many the post-quantum cryptography could be the thing warranting the adoption. All eye towards JDK-28 now.

I πŸ‡ΊπŸ‡¦ stand πŸ‡ΊπŸ‡¦ with πŸ‡ΊπŸ‡¦ Ukraine.

Sunday, June 28, 2026

Unexpected usefulness of the MessageDigest::isEqual method

How one would compare two Strings for equality in Java? There are a few options that come to mind, String::equals or Objects::equals would probably be among those. But for certain, not MessageDigest::isEqual, not even close.

So what gives? No doubts, String::equals is very efficient and returns result as soon as possible. In majority of cases, this is the desired behavior. But what if you compare secrets or alike? For example, tokens, API keys, etc. Not a big deal, right? It turns out it is, your code might be susceptible to so called timing attacks. The gist of it is that comparing two String values is the function of a) their sizes b) how many matching characters they have consequently. The attacker could apply brute force tactics and figure out what the size of the expected secret should be and then, with some patience, guess the characters. All that just by capturing how much time the comparison takes.

How MessageDigest::isEqual helps, you may ask? It actually examines all the bytes of the first argument, as such the calculation time depends only on its length and it does not depend on the length of the second argument (nor the contents of both).

So next time you see the snippet like this

MessageDigest.isEqual(
    token1.getBytes(StandardCharsets.UTF_8), 
    token2.getBytes(StandardCharsets.UTF_8));

where there is seemingly nothing going on related to message digests, you know why.

I πŸ‡ΊπŸ‡¦ stand πŸ‡ΊπŸ‡¦ with πŸ‡ΊπŸ‡¦ Ukraine.

Saturday, March 21, 2026

JDK-26: incremental improvement

Time for celebration once again: the JDK-26 was released just a few days ago! Although from all perspectives this release looks like incremental improvement (not a feature fest), it is worth paying close attention to.

  • JEP 500: Prepare to Make Final Mean Final: issues warnings about uses of deep reflection to mutate final fields. These warnings aim to prepare developers for a future release that ensures integrity by default by restricting final field mutation, which will make Java programs safer and potentially faster. Application developers can avoid both current warnings and future restrictions by selectively enabling the ability to mutate final fields where essential using --enable-final-field-mutation=module1,module2,... and --illegal-final-field-mutation=allow|warn}debug|deny command line arguments.

  • JEP 516: Ahead-of-Time Object Caching with Any GC: enhances the ahead-of-time cache, which enables the HotSpot Java Virtual Machine to improve startup and warmup time, so that it can be used with any garbage collector, including the low-latency Z Garbage Collector (ZGC). Achieve this by making it possible to load cached Java objects sequentially into memory from a neutral, GC-agnostic format, rather than map them directly into memory in a GC-specific format.

    GC-specific cached objects are mapped directly into memory, while GC-agnostic cached objects are streamed into memory. You can explicitly create a cache whose objects are in the streamable, GC-agnostic format by specifying -XX:+AOTStreamableObjects.

  • JEP 517: HTTP/3 for the HTTP Client API: updates the HTTP Client API to support the HTTP/3 protocol, so that libraries and applications can interact with HTTP/3 servers with minimal code change.

      var client = HttpClient
          .newBuilder()
          .version(HttpClient.Version.HTTP_3)
          .build();
      

    Interestingly, JDK does not provide HTTP/3 server implementation (yet), however Netty library, the de facto standard in Java ecosystem for implementing high performance protocol servers (and clients), is supporting HTTP/3 in 4.2 release line.

  • JEP 522: G1 GC: Improve Throughput by Reducing Synchronization: increases application throughput when using the G1 garbage collector by reducing the amount of synchronization required between application threads and GC threads.

  • JEP 504: Remove the Applet API: removes the Applet API, which was deprecated for removal in JDK 17. It is obsolete because neither recent JDK releases nor current web browsers support applets.

There are a few JEPs that made into JDK-26 as preview features, all of them are carried over from the previous JDK releases.

  • JEP 524: PEM Encodings of Cryptographic Objects (2nd Preview): introduces an API for encoding objects that represent cryptographic keys, certificates, and certificate revocation lists into the widely-used Privacy-Enhanced Mail (PEM) transport format, and for decoding from that format back into objects. This is a preview API feature.

  • JEP 525: Structured Concurrency (6th Preview): simplifies concurrent programming by introducing an API for structured concurrency. 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. This is a preview API feature.

  • JEP 526: Lazy Constants (2nd Preview): introduces an API for lazy constants, which are objects that hold unmodifiable data. Lazy constants are treated as true constants by the JVM, enabling the same performance optimizations that are enabled by declaring a field final. Compared to final fields, however, lazy constants offer greater flexibility as to the timing of their initialization. This is a preview API feature.

    This feature used to be known as stable values (JDK-25) and was renamed to lazy constants to better capture its intended use cases.

  • JEP 530: Primitive Types in Patterns, instanceof, and switch (4th Preview): enhances pattern matching by allowing primitive types in all pattern contexts, and extend instanceof and switch to work with all primitive types. This is a preview API feature.

  • JEP 529: Vector API (11th Incubator): introduces an API to express vector computations that reliably compile at runtime to optimal vector instructions on supported CPUs, thus achieving performance superior to equivalent scalar computations.

Indeed, the list of JEPs is not very impressive, but it does not make JDK-26 less important. There are quite a lot of interesting fixes and improvements in this release.

For more elaborate overview of GC changes, please refer to JDK 26 G1/Parallel/Serial GC changes blog post. Besides just JEP 517, the java.net.http.HttpClient got quite a lot of attention in this JDK release, certainly worth highlighting separately.

Another notable changes in JDK include:

This is pretty much it but we haven't talked about security related changes, it is just about time.

If you look for a bit more in-depth overview of the security related changes, please check out JDK 26 Security Enhancements blog post.

To summarize, the gems of JDK-26 release, in my opinion, are JEP 522: G1 GC: Improve Throughput by Reducing Synchronization, JEP 517: HTTP/3 for the HTTP Client API, and JDK-8369238: Allow virtual thread preemption on some common class initialization paths. Those are truly game changing enhancements for quite a wide audience of applications and services. Java continues to impress!

I πŸ‡ΊπŸ‡¦ stand πŸ‡ΊπŸ‡¦ with πŸ‡ΊπŸ‡¦ Ukraine.