<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://hanno.codes/feed.xml" rel="self" type="application/atom+xml" /><link href="https://hanno.codes/" rel="alternate" type="text/html" /><updated>2026-05-08T09:38:55+00:00</updated><id>https://hanno.codes/feed.xml</id><title type="html">hanno.codes</title><subtitle>Public speaker, Java developer, guitarist, singer.</subtitle><author><name>Hanno Embregts</name></author><entry><title type="html">Java 26 Is Here, And With It a Solid Foundation for the Future</title><link href="https://hanno.codes/2026/03/17/java-26-is-here/" rel="alternate" type="text/html" title="Java 26 Is Here, And With It a Solid Foundation for the Future" /><published>2026-03-17T02:30:00+00:00</published><updated>2026-03-17T02:30:00+00:00</updated><id>https://hanno.codes/2026/03/17/java-26-is-here</id><content type="html" xml:base="https://hanno.codes/2026/03/17/java-26-is-here/"><![CDATA[<p>Java 26 is here! Six months ago, we welcomed Java 25 into our hearts, which means it’s time for another fresh helping of Java features. This time, the set of features is a bit smaller compared to some of the previous releases, which can only mean one thing: the focus for this release was to provide a solid foundation for something big to be released soon™️! My hope is that the first JEPs out of Project Valhalla will be announced later this year. That hope is fueled by some of Java 26’s changes as they feel like appropriate preparation steps for the first Valhalla features (this is especially true for JEPs <a href="#jep-500-prepare-to-make-final-mean-final">500</a> and <a href="#jep-529-vector-api-eleventh-incubator">529</a>).</p>

<p>Regardless of any future plans, this post focuses on everything that has been added in this release, giving you a brief introduction to each of the features. Where applicable the differences with Java 25 are highlighted and a few typical use cases are provided, so that you’ll be more than ready to start using these features after reading this.</p>

<p><img src="/assets/images/blog/foundation.jpg" alt="Foundation" /></p>
<blockquote>
  <p>Photo by Rodolfo Quirós, from <a href="https://www.pexels.com/photo/selective-focus-photography-cement-2219024/">Pexels</a></p>
</blockquote>

<h2 id="jep-overview">JEP Overview</h2>

<p>To start off, let’s see an overview of the JEPs that ship with Java 26. This table contains their preview status, to which project they belong, what kind of features they add and the things that have changed since Java 25.</p>

<table>
  <thead>
    <tr>
      <th>JEP</th>
      <th>Title</th>
      <th>Status</th>
      <th>Project</th>
      <th>Feature Type</th>
      <th>Changes since previous Java version</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong><a href="#jep-500-prepare-to-make-final-mean-final">500</a></strong></td>
      <td>Prepare to Make Final Mean Final</td>
      <td> </td>
      <td>Core Libs</td>
      <td>Deprecation</td>
      <td>Warnings</td>
    </tr>
    <tr>
      <td><strong><a href="#jep-504-remove-the-applet-api">504</a></strong></td>
      <td>Remove the Applet API</td>
      <td> </td>
      <td>Client Libs</td>
      <td>Deprecation</td>
      <td>Deprecation</td>
    </tr>
    <tr>
      <td><strong><a href="#jep-516-ahead-of-time-object-caching-with-any-gc">516</a></strong></td>
      <td>Ahead-of-Time Object Caching with Any GC</td>
      <td> </td>
      <td>HotSpot</td>
      <td>Performance</td>
      <td>New feature</td>
    </tr>
    <tr>
      <td><strong><a href="#jep-517-http3-for-the-http-client-api">517</a></strong></td>
      <td>HTTP/3 for the HTTP Client API</td>
      <td> </td>
      <td>Core Libs</td>
      <td>Extension</td>
      <td>New feature</td>
    </tr>
    <tr>
      <td><strong><a href="#jep-522-g1-gc-improve-throughput-by-reducing-synchronization">522</a></strong></td>
      <td>G1 GC: Improve Throughput by Reducing Synchronization</td>
      <td> </td>
      <td>HotSpot</td>
      <td>Performance</td>
      <td>New feature</td>
    </tr>
    <tr>
      <td><strong><a href="#jep-524-pem-encodings-of-cryptographic-objects-second-preview">524</a></strong></td>
      <td>PEM Encodings of Cryptographic Objects</td>
      <td>Second Preview</td>
      <td>Security Libs</td>
      <td>Security</td>
      <td>Minor</td>
    </tr>
    <tr>
      <td><strong><a href="#jep-525-structured-concurrency-sixth-preview">525</a></strong></td>
      <td>Structured Concurrency</td>
      <td>Sixth Preview</td>
      <td>Loom</td>
      <td>Concurrency</td>
      <td>Minor</td>
    </tr>
    <tr>
      <td><strong><a href="#jep-526-lazy-constants-second-preview">526</a></strong></td>
      <td>Lazy Constants</td>
      <td>Second Preview</td>
      <td>Core Libs</td>
      <td>New API</td>
      <td>Major</td>
    </tr>
    <tr>
      <td><strong><a href="#jep-529-vector-api-eleventh-incubator">529</a></strong></td>
      <td>Vector API</td>
      <td>Eleventh Incubator</td>
      <td>Panama</td>
      <td>New API</td>
      <td>None</td>
    </tr>
    <tr>
      <td><strong><a href="#jep-530-primitive-types-in-patterns-instanceof-and-switch-fourth-preview">530</a></strong></td>
      <td>Primitive Types in Patterns, instanceof, and switch</td>
      <td>Fourth Preview</td>
      <td>Amber</td>
      <td>Language</td>
      <td>Minor</td>
    </tr>
  </tbody>
</table>

<h2 id="new-features">New features</h2>

<p>Let’s start with the JEPs that add brand-new features to Java 26.</p>

<h3 id="hotspot">HotSpot</h3>

<p>Java 26 introduces two new features in <a href="https://openjdk.org/groups/hotspot/">HotSpot</a>:</p>

<ul>
  <li>JEP 516: Ahead-of-Time Object Caching with Any GC</li>
  <li>JEP 522: G1 GC: Improve Throughput by Reducing Synchronization</li>
</ul>

<blockquote>
  <p>The HotSpot JVM is the runtime engine that is developed by Oracle. It translates Java bytecode into machine code for the host operating system’s processor architecture.</p>
</blockquote>

<h4 id="jep-516-ahead-of-time-object-caching-with-any-gc">JEP 516: Ahead-of-Time Object Caching with Any GC</h4>

<p>An important metric for applications that require a fast response time, such as web servers or real-time systems, is <a href="https://brooker.co.za/blog/2021/04/19/latency.html">tail latency</a> (the time it takes for a request to be processed).
It can be caused by either garbage collection pauses, or requests that are sent to a new, not-yet-warmed-up JVM instance.
The first cause can be mitigated by using a low-latency garbage collector, such as the Z Garbage Collector (ZGC), while the second can be mitigated by using the <a href="https://hanno.codes/2025/03/18/java-24-rolls-out-today/#jep-483-ahead-of-time-class-loading--linking">ahead-of-time cache</a>, which allows JVM instances to start up faster.</p>

<p>Java 24 introduced this ahead-of-time cache, storing classes in memory after reading, parsing, loading and linking them as a result of an initial <em>training run</em>.
Then, it could be re-used in subsequent runs of the application to improve startup time.
However, back then the use of the cache was somewhat limited, as cached Java objects were stored in a GC-specific format, making it incompatible with other garbage collectors like ZGC. JEP 516 extends support for the ahead-of-time cache to ZGC (and to any other garbage collector for that matter) by caching Java objects in a GC-agnostic format.</p>

<h5 id="what-makes-the-new-cache-format-gc-agnostic">What Makes the New Cache Format GC-Agnostic?</h5>

<p>Each garbage collector has its own policies for laying out objects in memory, which means that the memory addresses of cached objects are not valid across different garbage collectors.
To solve this problem, JEP 516 changes the cache format by replacing memory addresses with logical indices.
When the cache is loaded, these logical indices are converted back to memory addresses by <em>streaming</em> them into memory, materializing the cached objects in the process.</p>

<h5 id="usage">Usage</h5>

<p>The JVM will automatically cache objects in the streamable, GC-agnostic format if, in training, either ZGC or the <code class="language-plaintext highlighter-rouge">-XX:-UseCompressedOops</code> command-line option was used, or if the heap was larger than 32GB. 
In contrast, it will cache objects in the old, GC-specific format if, in training, the <code class="language-plaintext highlighter-rouge">-XX:+UseCompressedOops</code> (notice the ‘ plus’) command-line option was used. This indicates that the training environment had a heap smaller than 32GB and did not use ZGC.</p>

<p>If you want to force the use of the new GC-agnostic cache format regardless of the training environment, you can specify the <code class="language-plaintext highlighter-rouge">-XX:+AOTStreamableObjects</code> command-line option to make it happen.</p>

<h5 id="why-not-simply-create-zgc-specific-caches">Why Not Simply Create ZGC-Specific Caches?</h5>

<p>The alternative of creating ZGC-specific caches was not pursued because it would have required maintaining separate caches for each garbage collector. Moreover, the only benefit of a ZGC-specific cache would have been a slightly better performance on single-core machines. This benefit would have been negligible in practice, as the highly-concurrent ZGC was designed to perform well on multi-core machines rather than single-core machines, and it would not have justified the maintenance cost of multiple caches.</p>

<h5 id="more-information">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/516">JEP 516</a>.</p>

<h4 id="jep-522-g1-gc-improve-throughput-by-reducing-synchronization">JEP 522: G1 GC: Improve Throughput by Reducing Synchronization</h4>

<p><em>G1 GC</em> has been Java’s <a href="https://openjdk.org/jeps/248">default garbage collector since Java 9</a>. It’s been designed to provide high performance and low pause times for applications with large heaps, with the aim of balancing latency and throughput. To achieve this balance, G1 performs its work concurrently with the application, making the application threads share the CPU with GC threads. This situation requires thread synchronization, which unfortunately lowers throughput and increases latency.</p>

<p>JEP 522 proposes to improve both throughput and latency by reducing the amount of synchronization required between application threads and GC threads.</p>

<h5 id="why-is-synchronization-currently-necessary">Why Is Synchronization Currently Necessary?</h5>

<p>When G1 reclaims memory, live objects in the heap are copied to new memory regions, freeing up the space they leave behind. References to those objects must be updated to point to their new location. To prevent having to scan the entire heap for existing references to these objects, G1 maintains a data structure called the <em>card table</em>, which is updated every time an object reference is stored in a field. These updates are performed by pieces of code called <em>write barriers</em>, which G1 injects into the application in cooperation with the Just-In-Time (JIT) compiler.</p>

<p>Scanning the card table is an efficient operation and will typically fit within a GC pause’s time window. However, in  environments where objects are allocated very frequently the card table may grow too large to be scanned within the timespan of G1’s pause time goal. To avoid that, G1 optimizes the card table in the background via separate optimizer threads. This approach can only work if the card table is updated in a thread-safe way, which is currently achieved by synchronizing the optimizer threads with the application threads. Arguably, this leads to more complicated and slower write-barrier code.</p>

<h5 id="towards-a-second-card-table">Towards A Second Card Table</h5>

<p>JEP 522 proposes to introduce a <em>second card table</em>, to make sure the optimizer threads and application threads no longer interfere. The write barriers in the application threads will update the first card table without any synchronization, while the optimizer threads will update the second, initially empty, card table.</p>

<p>When G1 determines that scanning the current card table during a pause would likely breach the pause‑time target, it atomically switches the two card tables. Application threads then continue to write to the now‑empty table (the former “second” table), while dedicated optimizer threads process the previously‑filled table (the former “first” table) without any additional synchronization. G1 repeats this swapping as needed so that the work required on the active card table stays within the desired limits.</p>

<p>This approach reduces the amount of synchronization required between application and optimizer threads. In applications that heavily modify object-reference fields, throughput gains of 5-15% can be expected. On top of that, because the write barrier code can be a lot simpler, additional throughput gains of up to 5% have been observed in x64 architectures, even in applications that don’t heavily modify object-reference fields.</p>

<p>The two card tables are identical in size, each consuming the same extra native memory. Together they occupy roughly 0.2% of the Java heap, which translates to about 2MB of native memory for every gigabyte of heap space. This modest overhead is well worth the sizable performance gains—especially when you consider that, before Java 20, G1 needed more than eight times the memory that the second card table now requires.</p>

<h5 id="more-information-1">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/522">JEP 522</a>.</p>

<h3 id="core-libs">Core Libs</h3>

<p>Java 26 introduces a single new feature that is part of the Core Libs:</p>

<ul>
  <li>JEP 517: HTTP/3 for the HTTP Client API</li>
</ul>

<h4 id="jep-517-http3-for-the-http-client-api">JEP 517: HTTP/3 for the HTTP Client API</h4>

<p>Since Java 11, a modern HTTP client API is available within the Java Platform. It supports both HTTP/1.1 and HTTP/2 and was designed to potentially support future versions as well. In its current form, the API assumes HTTP/2 by default, but it can revert to HTTP/1.1 should the target server not support a newer HTTP version.</p>

<p>The code example below demonstrates the ease of use and protocol agnosticity of the API:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">java.net.http.*</span><span class="o">;</span>

<span class="o">...</span>
<span class="kt">var</span> <span class="n">client</span> <span class="o">=</span> <span class="nc">HttpClient</span><span class="o">.</span><span class="na">newHttpClient</span><span class="o">();</span>
<span class="kt">var</span> <span class="n">request</span> <span class="o">=</span> <span class="nc">HttpRequest</span><span class="o">.</span><span class="na">newBuilder</span><span class="o">(</span><span class="no">URI</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="s">"https://hanno.codes"</span><span class="o">)).</span><span class="na">GET</span><span class="o">().</span><span class="na">build</span><span class="o">();</span>
<span class="kt">var</span> <span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="na">send</span><span class="o">(</span><span class="n">request</span><span class="o">,</span> <span class="nc">HttpResponse</span><span class="o">.</span><span class="na">BodyHandlers</span><span class="o">.</span><span class="na">ofString</span><span class="o">());</span>
<span class="k">assert</span> <span class="n">response</span><span class="o">.</span><span class="na">statusCode</span><span class="o">()</span> <span class="o">==</span> <span class="mi">200</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">htmlText</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="na">body</span><span class="o">();</span>
<span class="k">assert</span> <span class="n">htmlText</span><span class="o">.</span><span class="na">contains</span><span class="o">(</span><span class="s">"Java"</span><span class="o">);</span>
</code></pre></div></div>

<p>As you can see, we didn’t specify any HTTP version in this code example–the API assumes HTTP/2 by default.</p>

<h5 id="http3-https-next-version">HTTP/3: HTTP’s Next Version</h5>

<p>HTTP/3 was standardized in 2022 by the <a href="https://www.ietf.org/">IETF</a>, using the <a href="https://en.wikipedia.org/wiki/QUIC">QUIC</a> transport-layer protocol over TCP. Applications that use the HTTP/3 protocol can benefit from multiplexing, faster handshakes, avoidance of network congestion issues and more reliable transport, among others. Most web browsers <a href="https://caniuse.com/http3">already support HTTP/3</a> and <a href="https://w3techs.com/technologies/details/ce-http3">about a third of all web sites</a> currently benefit from its features. So this seems like a good time to start supporting it in the HTTP client API, which is exactly what JEP 517 is proposing.</p>

<h5 id="using-http3-in-java-code">Using HTTP/3 In Java Code</h5>

<p>In Java 26, the HTTP client API requires you to opt-in to HTTP/3 by configuring an instance of either <code class="language-plaintext highlighter-rouge">HttpClient</code> or <code class="language-plaintext highlighter-rouge">HttpRequest</code> with the <code class="language-plaintext highlighter-rouge">HTTP_3</code> version. For example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// for reuse with multiple requests</span>
<span class="kt">var</span> <span class="n">http3Client</span> <span class="o">=</span> <span class="nc">HttpClient</span><span class="o">.</span><span class="na">newBuilder</span><span class="o">().</span><span class="na">version</span><span class="o">(</span><span class="nc">HttpClient</span><span class="o">.</span><span class="na">Version</span><span class="o">.</span><span class="na">HTTP_3</span><span class="o">).</span><span class="na">build</span><span class="o">();</span>

<span class="c1">// just for a single request</span>
<span class="kt">var</span> <span class="n">http3Request</span> <span class="o">=</span> <span class="nc">HttpRequest</span><span class="o">.</span><span class="na">newBuilder</span><span class="o">(</span><span class="no">URI</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="s">"https://hanno.codes"</span><span class="o">))</span>
    <span class="o">.</span><span class="na">version</span><span class="o">(</span><span class="nc">HttpClient</span><span class="o">.</span><span class="na">Version</span><span class="o">.</span><span class="na">HTTP_3</span><span class="o">)</span>
    <span class="o">.</span><span class="na">GET</span><span class="o">().</span><span class="na">build</span><span class="o">();</span>
</code></pre></div></div>

<p>Once HTTP/3 has been chosen—either in the request itself or in the client—you transmit the request just as you normally would. If the destination server lacks HTTP/3 support, the request is automatically and transparently rolled back to HTTP/2 or, if necessary, to HTTP/1.1.</p>

<h5 id="negotiating-protocol-versions">Negotiating Protocol Versions</h5>

<p>The HTTP client API can’t know for sure if a target server will support HTTP/3. Moreover, existing HTTP/1.1 and HTTP/2 connections cannot be upgraded to HTTP/3, since HTTP/1.1 and HTTP/2 are built on top of TCP, while HTTP/3’s QUIC is based on UDP datagrams. So the API needs a way to negotiate protocol versions–in order to do that, it’s been equipped with four separate approaches:</p>

<ol>
  <li>
    <p><strong>Try HTTP/3 first, fall back if it times‑out</strong> – Initiate the request with HTTP/3; if a connection cannot be established within a reasonable timeout, automatically downgrade to HTTP/2 or HTTP/1.1. <em>(matches a <code class="language-plaintext highlighter-rouge">HttpRequest</code> whose preferred version is set to <code class="language-plaintext highlighter-rouge">HTTP_3</code>)</em></p>
  </li>
  <li>
    <p><strong>Race HTTP/3 against an older protocol</strong> – Open both an HTTP/3 connection and an HTTP/2 or HTTP/1.1 connection simultaneously and use whichever succeeds first. <em>(occurs when the <code class="language-plaintext highlighter-rouge">HttpClient</code> prefers <code class="language-plaintext highlighter-rouge">HTTP_3</code> but the <code class="language-plaintext highlighter-rouge">HttpRequest</code> does not specify a preferred version)</em></p>
  </li>
  <li>
    <p><strong>Start with HTTP/2 or 1.1 and switch on discovery</strong> – Send the initial request over HTTP/2 or HTTP/1.1. If the server’s response indicates that HTTP/3 is available, switch to HTTP/3 for all following requests. <em>(triggered by setting <code class="language-plaintext highlighter-rouge">Http3DiscoveryMode.ALT_SVC</code> for the <code class="language-plaintext highlighter-rouge">H3_DISCOVERY</code> option, with at least one of the clients or requests preferring <code class="language-plaintext highlighter-rouge">HTTP_3</code>)</em></p>
  </li>
  <li>
    <p><strong>Force HTTP/3 only</strong> – Send every request exclusively over HTTP/3; if the server cannot reply with HTTP/3, treat it as a failure and do not fall back to earlier protocols. <em>(enabled by <code class="language-plaintext highlighter-rouge">Http3DiscoveryMode.HTTP_3_URI_ONLY</code> for the <code class="language-plaintext highlighter-rouge">H3_DISCOVERY</code> option, with at least one client or request preferring <code class="language-plaintext highlighter-rouge">HTTP_3</code>)</em></p>
  </li>
</ol>

<p>The four methods each come with their own drawbacks:</p>

<ul>
  <li>Option 1 incurs a timeout delay before falling back.</li>
  <li>Option 2 may waste resources by establishing an HTTP/3 connection that is never reused.</li>
  <li>Option 3 requires an initial HTTP/2 or HTTP/1.1 round‑trip before any HTTP/3 benefits are realized.</li>
  <li>Option 4 only works when you already know that the target server supports HTTP/3.</li>
</ul>

<p>HTTP/3 is not as widely deployed as its older counterparts, which is why no single approach can work in all circumstances. This is also the main reason why HTTP/3 can’t be made the default protocol version at this time, though this may be change in the future when HTTP/3 is more widely adopted.</p>

<h5 id="more-information-2">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/517">JEP 517</a>.</p>

<h2 id="repreviews">Repreviews</h2>

<p>Now it’s time to take a look at a few features that might already be familiar to you, because they were introduced in a previous version of Java. They have been repreviewed in Java 26, with only minor changes compared to Java 25 in most cases.</p>

<h3 id="jep-524-pem-encodings-of-cryptographic-objects-second-preview">JEP 524: PEM Encodings of Cryptographic Objects (Second Preview)</h3>

<p>Within a Java context, cryptographic objects such as public keys, private keys and certificates can be easily created and distributed. But outside of the Java world, the de facto standard is the <a href="https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail">Privacy-Enhanced Mail</a> (PEM) format. Let’s see an example of a PEM-encoded cryptographic object:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEi/kRGOL7wCPTN4KJ2ppeSt5UYB6u
cPjjuKDtFTXbguOIFDdZ65O/8HTUqS/sVzRF+dg7H3/tkQ/36KdtuADbwQ==
-----END PUBLIC KEY-----
</code></pre></div></div>

<p>The Java Platform currently doesn’t include an easy-to-use API for decoding and encoding text in the PEM format, which means that decoding a PEM-encoded key can be a tedious job that involves careful parsing of the source PEM text. To further illustrate this point, encrypting and decrypting a private key currently requires over a dozen lines of code.</p>

<p>To solve this problem, JEP 524 introduces an API that can encode objects to the PEM format. It effectively acts as a bridge between Base64 and cryptographic objects. It involves a new interface and three new classes, in the <code class="language-plaintext highlighter-rouge">java.security</code> package:</p>

<dl>
  <dt><a href="https://cr.openjdk.org/~ascarpino/pem26/api/java.base/java/security/DEREncodable.html"><code class="language-plaintext highlighter-rouge">DEREncodable</code></a></dt>
  <dd>A sealed interface that groups together all cryptographic objects that support converting their instances to and from byte arrays in the <a href="https://en.wikipedia.org/wiki/X.690#DER_encoding">Distinguished Encoding Rules</a> (DER) format.</dd>
  <dt><a href="https://cr.openjdk.org/~ascarpino/pem26/api/java.base/java/security/PEMEncoder.html"><code class="language-plaintext highlighter-rouge">PEMEncoder</code></a></dt>
  <dd>A class that declares methods for encoding <code class="language-plaintext highlighter-rouge">DEREncodable</code> objects into PEM text.</dd>
  <dt><a href="https://cr.openjdk.org/~ascarpino/pem26/api/java.base/java/security/PEMDecoder.html"><code class="language-plaintext highlighter-rouge">PEMDecoder</code></a></dt>
  <dd>A class that declares methods for decoding PEM text to <code class="language-plaintext highlighter-rouge">DEREncodable</code> objects.</dd>
  <dt><a href="https://cr.openjdk.org/~ascarpino/pem26/api/java.base/java/security/PEM.html"><code class="language-plaintext highlighter-rouge">PEM</code></a></dt>
  <dd>A record that implements <code class="language-plaintext highlighter-rouge">DEREncodable</code>, which can hold any type of PEM data. It allows you to encode and decode PEM tests yielding cryptographic objects for which no Java representation currently exists.</dd>
</dl>

<h5 id="typical-usage">Typical Usage</h5>

<p>The following code example shows typical usage of the API:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">PrivateKey</span> <span class="n">privateKey</span> <span class="o">=</span> <span class="o">...;</span>
<span class="nc">PublicKey</span> <span class="n">publicKey</span> <span class="o">=</span> <span class="o">...;</span>

<span class="c1">// let's encode a cryptographic object!</span>
<span class="nc">PEMEncoder</span> <span class="n">pemEncoder</span> <span class="o">=</span> <span class="nc">PEMEncoder</span><span class="o">.</span><span class="na">of</span><span class="o">();</span>

<span class="c1">// this returns PEM text in a byte array</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">privateKeyPem</span> <span class="o">=</span> <span class="n">pemEncoder</span><span class="o">.</span><span class="na">encode</span><span class="o">(</span><span class="n">privateKey</span><span class="o">);</span>

<span class="c1">// this returns PEM text in a String</span>
<span class="nc">String</span> <span class="n">keyPairPem</span> <span class="o">=</span> <span class="n">pemEncoder</span><span class="o">.</span><span class="na">encodeToString</span><span class="o">(</span><span class="k">new</span> <span class="nc">KeyPair</span><span class="o">(</span><span class="n">privateKey</span><span class="o">,</span> <span class="n">publicKey</span><span class="o">));</span> 

<span class="c1">// this returns encrypted PEM text</span>
<span class="nc">String</span> <span class="n">password</span> <span class="o">=</span> <span class="s">"java-first-java-always"</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">pem</span> <span class="o">=</span> <span class="n">pemEncoder</span><span class="o">.</span><span class="na">withEncryption</span><span class="o">(</span><span class="n">password</span><span class="o">).</span><span class="na">encodeToString</span><span class="o">(</span><span class="n">privateKey</span><span class="o">);</span>

<span class="c1">// let's decode a cryptographic object!</span>
<span class="nc">PEMDecoder</span> <span class="n">pemDecoder</span> <span class="o">=</span> <span class="nc">PEMDecoder</span><span class="o">.</span><span class="na">of</span><span class="o">();</span>

<span class="c1">// this returns a DEREncodable, so we need to pattern-match</span>
<span class="k">switch</span> <span class="o">(</span><span class="n">pemDecoder</span><span class="o">.</span><span class="na">decode</span><span class="o">(</span><span class="n">pem</span><span class="o">))</span> <span class="o">{</span>
    <span class="k">case</span> <span class="nc">PublicKey</span> <span class="n">publicKey</span> <span class="o">-&gt;</span> <span class="o">...;</span>
    <span class="k">case</span> <span class="nc">PrivateKey</span> <span class="n">privateKey</span> <span class="o">-&gt;</span> <span class="o">...;</span>
    <span class="k">default</span> <span class="o">-&gt;</span> <span class="k">throw</span> <span class="k">new</span> <span class="nc">IllegalArgumentException</span><span class="o">(</span><span class="s">"Unsupported cryptographic object"</span><span class="o">);</span>
<span class="o">}</span>

<span class="c1">// alternatively, if you know the type of the encoded cryptographic object in advance:</span>
<span class="nc">PrivateKey</span> <span class="n">key</span> <span class="o">=</span> <span class="n">pemDecoder</span><span class="o">.</span><span class="na">decode</span><span class="o">(</span><span class="n">pem</span><span class="o">,</span> <span class="nc">PrivateKey</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>

<span class="c1">// this decodes an encrypted cryptographic object</span>
<span class="nc">PrivateKey</span> <span class="n">decryptedkey</span> <span class="o">=</span> <span class="n">pemDecoder</span><span class="o">.</span><span class="na">withDecryption</span><span class="o">(</span><span class="n">password</span><span class="o">).</span><span class="na">decode</span><span class="o">(</span><span class="n">pem</span><span class="o">,</span> <span class="nc">PrivateKey</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
</code></pre></div></div>

<h5 id="preview-warning">Preview Warning</h5>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="whats-different-from-java-25">What’s Different From Java 25?</h4>

<p>A few minor changes were made to the API compared to Java 25:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">PEMRecord</code> was renamed to <code class="language-plaintext highlighter-rouge">PEM</code>, and includes a <code class="language-plaintext highlighter-rouge">decode()</code> method that returns decoded Base64 content;</li>
  <li>The <code class="language-plaintext highlighter-rouge">PEMEncoder</code> and <code class="language-plaintext highlighter-rouge">PEMDecoder</code> classes now support the encryption and decryption of <code class="language-plaintext highlighter-rouge">KeyPair</code> and <code class="language-plaintext highlighter-rouge">PKCS8EncodedKeySpec</code> objects;</li>
  <li>Finally, a few changes were made to the <code class="language-plaintext highlighter-rouge">EncryptedPrivateKeyInfo</code> class:
    <ul>
      <li>The <code class="language-plaintext highlighter-rouge">encryptKey</code> methods are now named <code class="language-plaintext highlighter-rouge">encrypt</code>, and they now accept <code class="language-plaintext highlighter-rouge">DEREncodable</code> objects rather than <code class="language-plaintext highlighter-rouge">PrivateKey</code> objects, enabling the encryption of <code class="language-plaintext highlighter-rouge">KeyPair</code> and <code class="language-plaintext highlighter-rouge">PKCS8EncodedKeySpec</code> objects.</li>
      <li>It includes <code class="language-plaintext highlighter-rouge">getKeyPair</code> methods that decrypt PKCS#8-encoded text containing a <code class="language-plaintext highlighter-rouge">PublicKey</code>.</li>
      <li>The exceptions thrown by the <code class="language-plaintext highlighter-rouge">getKey</code> methods are now aligned with those thrown by the nearby <code class="language-plaintext highlighter-rouge">getKeySpec</code> methods.</li>
    </ul>
  </li>
</ul>

<h4 id="more-information-3">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/524">JEP 524</a>.</p>

<h3 id="jep-525-structured-concurrency-sixth-preview">JEP 525: Structured Concurrency (Sixth Preview)</h3>

<p>Java’s take on concurrency has always been <em>unstructured</em>, meaning that tasks run independently of each other. There’s no hierarchy, scope, or other structure involved, which means errors or cancellation intent is hard to communicate. To illustrate this, let’s look at a code example that takes place in a restaurant:</p>

<blockquote>
  <p>These code examples were taken from my conference talk <a href="https://hanno.codes/talks/#javas-concurrency-journey-continues">“Java’s Concurrency Journey Continues! Exploring Structured Concurrency and Scoped Values”</a>.</p>
</blockquote>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">MultiWaiterRestaurant</span> <span class="kd">implements</span> <span class="nc">Restaurant</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">MultiCourseMeal</span> <span class="nf">announceMenu</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">ExecutionException</span><span class="o">,</span> <span class="nc">InterruptedException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">grover</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Grover"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">rosita</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Rosita"</span><span class="o">);</span>

        <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">executor</span> <span class="o">=</span> <span class="nc">Executors</span><span class="o">.</span><span class="na">newVirtualThreadPerTaskExecutor</span><span class="o">())</span> <span class="o">{</span>
            <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">starter</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">grover</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">STARTER</span><span class="o">));</span>
            <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">main</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">MAIN</span><span class="o">));</span>
            <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">dessert</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">rosita</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">DESSERT</span><span class="o">));</span>

            <span class="k">return</span> <span class="k">new</span> <span class="nf">MultiCourseMeal</span><span class="o">(</span><span class="n">starter</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">main</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">dessert</span><span class="o">.</span><span class="na">get</span><span class="o">());</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Note that the <code class="language-plaintext highlighter-rouge">announceCourse(..)</code> method in the <code class="language-plaintext highlighter-rouge">Waiter</code> class sometimes fails with an <code class="language-plaintext highlighter-rouge">OutOfStockException</code>, because one of the ingredients for the course might not be in stock. This can lead to some problems:</p>

<ul>
  <li>If <code class="language-plaintext highlighter-rouge">zoe.announceCourse(CourseType.MAIN)</code> takes a long time to execute but <code class="language-plaintext highlighter-rouge">grover.announceCourse(CourseType.STARTER)</code> fails in the meantime, the <code class="language-plaintext highlighter-rouge">announceMenu(..)</code> method will unnecessarily wait for the main course announcement by blocking on <code class="language-plaintext highlighter-rouge">main.get()</code>, instead of cancelling it (which would be the sensible thing to do).</li>
  <li>If an exception happens in <code class="language-plaintext highlighter-rouge">zoe.announceCourse(CourseType.MAIN)</code>, <code class="language-plaintext highlighter-rouge">main.get()</code> will throw it, but <code class="language-plaintext highlighter-rouge">grover.announceCourse(CourseType.STARTER)</code> will continue to run in its own thread, resulting in thread leakage.</li>
  <li>If the thread executing <code class="language-plaintext highlighter-rouge">announceMenu(..)</code> is interrupted, the interruption will not propagate to the subtasks: all threads that run an <code class="language-plaintext highlighter-rouge">announceCourse(..)</code> invocation will leak, continuing to run even after <code class="language-plaintext highlighter-rouge">announceMenu()</code> has failed.</li>
</ul>

<p>Ultimately the problem here is that our program is logically structured with task-subtask relationships, but these relationships exist only in the mind of the developer. We might all prefer structured code that reads like a sequential story, but this example simply doesn’t meet that criterion.</p>

<p>In contrast, the execution of single-threaded code <em>always</em> enforces a hierarchy of tasks and subtasks, as shown by the single-threaded version of our restaurant example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">SingleWaiterRestaurant</span> <span class="kd">implements</span> <span class="nc">Restaurant</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">MultiCourseMeal</span> <span class="nf">announceMenu</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">OutOfStockException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">elmo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Elmo"</span><span class="o">);</span>

        <span class="nc">Course</span> <span class="n">starter</span> <span class="o">=</span> <span class="n">elmo</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">STARTER</span><span class="o">);</span>
        <span class="nc">Course</span> <span class="n">main</span> <span class="o">=</span> <span class="n">elmo</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">MAIN</span><span class="o">);</span>
        <span class="nc">Course</span> <span class="n">dessert</span> <span class="o">=</span> <span class="n">elmo</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">DESSERT</span><span class="o">);</span>

        <span class="k">return</span> <span class="k">new</span> <span class="nf">MultiCourseMeal</span><span class="o">(</span><span class="n">starter</span><span class="o">,</span> <span class="n">main</span><span class="o">,</span> <span class="n">dessert</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here, we don’t have <em>any</em> of the problems we had before.
Our waiter Elmo will announce the courses in exactly the right order, and if one subtask fails the remaining one(s) won’t even be started.
And because all work runs in the same thread, there is no risk of thread leakage.</p>

<p>It became apparent from these examples that concurrent programming would be a lot easier and more intuitive if enforcing the hierarchy of tasks and subtasks was possible, just like with single-threaded code.</p>

<h4 id="introducing-structured-concurrency">Introducing Structured Concurrency</h4>

<p>In a structured concurrency approach, threads have a clear hierarchy, their own scope, and clear entry and exit points. Structured concurrency arranges threads hierarchically, akin to function calls, forming a tree with parent-child relationships. Execution scopes persist until all child threads complete, matching code structure.</p>

<h4 id="shutdown-on-failure">Shutdown on Failure</h4>

<p>Let’s look at a structured, concurrent version of our example now:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">StructuredConcurrencyRestaurant</span> <span class="kd">implements</span> <span class="nc">Restaurant</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">MultiCourseMeal</span> <span class="nf">announceMenu</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">ExecutionException</span><span class="o">,</span> <span class="nc">InterruptedException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">grover</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Grover"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">rosita</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Rosita"</span><span class="o">);</span>

        <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">scope</span> <span class="o">=</span> <span class="nc">StructuredTaskScope</span><span class="o">.</span><span class="na">open</span><span class="o">())</span> <span class="o">{</span>
            <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">starter</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">grover</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">STARTER</span><span class="o">));</span>
            <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">main</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">MAIN</span><span class="o">));</span>
            <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">dessert</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">rosita</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">DESSERT</span><span class="o">));</span>

            <span class="n">scope</span><span class="o">.</span><span class="na">join</span><span class="o">();</span> <span class="c1">// 1</span>

            <span class="k">return</span> <span class="k">new</span> <span class="nf">MultiCourseMeal</span><span class="o">(</span><span class="n">starter</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">main</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">dessert</span><span class="o">.</span><span class="na">get</span><span class="o">());</span> <span class="c1">// 2</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The scope’s purpose is to keep the threads together. At <code class="language-plaintext highlighter-rouge">1</code>, we wait (<code class="language-plaintext highlighter-rouge">join</code>) until all threads are done with their work. If one of the threads is interrupted, an <code class="language-plaintext highlighter-rouge">InterruptedException</code> is thrown. A <code class="language-plaintext highlighter-rouge">RuntimeException</code> can also be thrown here, if an exception occurs in one of the spawned threads. Once we reach <code class="language-plaintext highlighter-rouge">2</code>, we can be sure everything has gone well, and we can retrieve and process the results.</p>

<p>Actually, the main difference with the code we had before is the fact that we create threads (<code class="language-plaintext highlighter-rouge">fork</code>) within a new <code class="language-plaintext highlighter-rouge">scope</code>. Now we can be certain that the lifetimes of the three threads are confined to this scope, which coincides with the body of the try-with-resources statement.</p>

<p>Furthermore, we’ve gained <em>short-circuiting behaviour</em>. When one of the <code class="language-plaintext highlighter-rouge">announceCourse(..)</code> subtasks fails, the others are canceled if they didn’t complete yet. We’ve also gained <em>cancellation propagation</em>. When the thread that runs <code class="language-plaintext highlighter-rouge">announceMenu()</code> is interrupted before or during the call to <code class="language-plaintext highlighter-rouge">scope.join()</code>, all subtasks are cancelled automatically when the thread exits the scope.</p>

<h4 id="shutdown-on-success">Shutdown on Success</h4>

<p>The factory method that gave us the scope (<code class="language-plaintext highlighter-rouge">StructuredTaskScope.open()</code>) implements a shutdown-on-failure policy by default, which cancels any remaining tasks in the scope if one of the tasks has failed. A shutdown-on-success policy is also available: it cancels any remaining tasks in the scope if one of the tasks has succeeded. It can be used to avoid doing unnecessary work when a successful result has already been achieved.</p>

<p>We can use a shutdown-on-success policy by calling an overload of the <code class="language-plaintext highlighter-rouge">StructuredTaskScope.open()</code> method that takes a <code class="language-plaintext highlighter-rouge">Joiner</code> as its parameter. Let’s see what that would look like:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">record</span> <span class="nf">DrinkOrder</span><span class="o">(</span><span class="nc">Guest</span> <span class="n">guest</span><span class="o">,</span> <span class="nc">Drink</span> <span class="n">drink</span><span class="o">)</span> <span class="o">{}</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">StructuredConcurrencyBar</span> <span class="kd">implements</span> <span class="nc">Bar</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">DrinkOrder</span> <span class="nf">determineDrinkOrder</span><span class="o">(</span><span class="nc">Guest</span> <span class="n">guest</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">InterruptedException</span><span class="o">,</span> <span class="nc">ExecutionException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">elmo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Elmo"</span><span class="o">);</span>

        <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">scope</span> <span class="o">=</span> <span class="nc">StructuredTaskScope</span><span class="o">.</span><span class="na">open</span><span class="o">(</span><span class="nc">Joiner</span><span class="o">.&lt;</span><span class="nc">DrinkOrder</span><span class="o">&gt;</span><span class="n">anySuccessfulOrThrow</span><span class="o">()))</span> <span class="o">{</span>
            <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">getDrinkOrder</span><span class="o">(</span><span class="n">guest</span><span class="o">,</span> <span class="no">BEER</span><span class="o">,</span> <span class="no">WINE</span><span class="o">,</span> <span class="no">JUICE</span><span class="o">));</span>
            <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">elmo</span><span class="o">.</span><span class="na">getDrinkOrder</span><span class="o">(</span><span class="n">guest</span><span class="o">,</span> <span class="no">COFFEE</span><span class="o">,</span> <span class="no">TEA</span><span class="o">,</span> <span class="no">COCKTAIL</span><span class="o">,</span> <span class="no">DISTILLED</span><span class="o">));</span>

            <span class="k">return</span> <span class="n">scope</span><span class="o">.</span><span class="na">join</span><span class="o">();</span> <span class="c1">// 1</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>In this example the waiter is responsible for getting a valid <code class="language-plaintext highlighter-rouge">DrinkOrder</code> object based on guest preference and the drinks supply at the bar.
In the method <code class="language-plaintext highlighter-rouge">Waiter.getDrinkOrder(Guest guest, DrinkCategory... categories)</code>, the waiter starts to list all available drinks in the drink categories that were passed to the method.
Once a guest hears something they like, they respond and the waiter creates a drink order. When this happens, the <code class="language-plaintext highlighter-rouge">getDrinkOrder(..)</code> method returns a <code class="language-plaintext highlighter-rouge">DrinkOrder</code> object and the scope will shut down. 
This means that any unfinished subtasks (such as the one in which Elmo is still listing different kinds of tea) will be cancelled.
The <code class="language-plaintext highlighter-rouge">join()</code> method at <code class="language-plaintext highlighter-rouge">1</code> will either return a valid <code class="language-plaintext highlighter-rouge">DrinkOrder</code> object, or throw a <code class="language-plaintext highlighter-rouge">RuntimeException</code> if one of the subtasks has failed.</p>

<h4 id="more-shutdown-policies">More Shutdown Policies</h4>

<p>We’ve seen examples of two shutdown policies so far, but four more are provided out-of-the-box through the static factory methods in the <code class="language-plaintext highlighter-rouge">StructuredTaskScope.Joiner</code> interface. For example, <code class="language-plaintext highlighter-rouge">Joiner.allSuccessfulOrThrow()</code> will keep the scope alive until all subtasks have completed successfully, and cancels it if any subtasks fails. And <code class="language-plaintext highlighter-rouge">Joiner.awaitAll()</code> will wait for all subtasks to complete, whether they complete successfully or not. It’s also possible to create your own shutdown policies by implementing the <code class="language-plaintext highlighter-rouge">Joiner</code> interface. That will allow you to have full control over when the scope will be shut down and what results will be collected.</p>

<h4 id="whats-different-from-java-25-1">What’s Different From Java 25?</h4>

<p>A few minor changes were made to the API compared to Java 25:</p>

<ul>
  <li>A new method in the <code class="language-plaintext highlighter-rouge">Joiner</code> interface, <code class="language-plaintext highlighter-rouge">onTimeout()</code>, allows implementations of that interface to return a result when a timeout expires.</li>
  <li><code class="language-plaintext highlighter-rouge">Joiner::allSuccessfulOrThrow()</code> now returns a list of results instead of a stream of subtasks.</li>
  <li><code class="language-plaintext highlighter-rouge">Joiner::anySuccessfulResultOrThrow()</code> was renamed to the slightly simpler <code class="language-plaintext highlighter-rouge">anySuccessfulOrThrow()</code>.</li>
  <li>The static <code class="language-plaintext highlighter-rouge">open</code> method that used to take a <code class="language-plaintext highlighter-rouge">Joiner</code> and a <code class="language-plaintext highlighter-rouge">Function</code> to modify the default configuration now takes a <code class="language-plaintext highlighter-rouge">Joiner</code> and a  <code class="language-plaintext highlighter-rouge">UnaryOperator</code>.</li>
</ul>

<h4 id="preview-warning-1">Preview Warning</h4>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-4">More Information</h4>

<p><a href="https://openjdk.org/jeps/525">JEP 525</a> has more details on the current state of this feature, should you wish to learn more.</p>

<h3 id="jep-526-lazy-constants-second-preview">JEP 526: Lazy Constants (Second Preview)</h3>

<p>Immutable objects are a far less complicated concept than mutable objects, because they can only be in a single state and can be shared freely across multiple threads.
Currently, the main tool to achieve immutability in Java is <code class="language-plaintext highlighter-rouge">final</code> fields.
But they come with two drawbacks, restricting their potential in many real-world applications:</p>

<ul>
  <li>they must be set eagerly;</li>
  <li>the order in which multiple <code class="language-plaintext highlighter-rouge">final</code> fields are initialized can never be changed, as it is determined by the <a href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-12.html#jls-12.4">textual order</a> in which the fields are declared.</li>
</ul>

<p>Consider the use of immutability in the following code example, which takes place in a guitar store domain:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">OrderController</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">Logger</span> <span class="n">logger</span> <span class="o">=</span> <span class="nc">Logger</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="nc">OrderController</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>

    <span class="kt">void</span> <span class="nf">submitOrder</span><span class="o">(</span><span class="nc">User</span> <span class="n">user</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Guitar</span><span class="o">&gt;</span> <span class="n">guitar</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Ordering new guitars..."</span><span class="o">);</span>
        
        <span class="c1">// ...</span>
        
        <span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"New guitars have been ordered, let's get to work!"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Whenever an instance of <code class="language-plaintext highlighter-rouge">OrderController</code> is created, the <code class="language-plaintext highlighter-rouge">logger</code> field is initialized eagerly, which potentially makes creating an <code class="language-plaintext highlighter-rouge">OrderController</code> slow.
And this might not be the only place in our application where a <code class="language-plaintext highlighter-rouge">logger</code> field is initialized eagerly:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">GuitarStore</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">OrderController</span> <span class="no">ORDERS</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">OrderController</span><span class="o">();</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">GuitarRepository</span> <span class="no">GUITARS</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">GuitarRepository</span><span class="o">();</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">ManufacturerService</span> <span class="no">MANUFACTURERS</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ManufacturerService</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>

<p>All this initialization work causes the application to start up more slowly, and the worst thing is: it may not even be necessary!
If a user is simply browsing the guitar store, with no intention of ordering a new guitar, the <code class="language-plaintext highlighter-rouge">OrderController</code> won’t even be called and we will have initialized the <code class="language-plaintext highlighter-rouge">logger</code> field for nothing.</p>

<h5 id="sacrificing-immutability-for-more-flexible-initialization">Sacrificing Immutability For More Flexible Initialization</h5>

<p>The only alternative we currently have is to resort to a mutability-based approach, in which we delay the initialization of complex objects to as late a time as possible:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">OrderController</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="nc">Logger</span> <span class="n">logger</span><span class="o">;</span>

    <span class="nc">Logger</span> <span class="nf">getLogger</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">logger</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">logger</span> <span class="o">=</span> <span class="nc">Logger</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="nc">OrderController</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="k">return</span> <span class="n">logger</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kt">void</span> <span class="nf">submitOrder</span><span class="o">(</span><span class="nc">User</span> <span class="n">user</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Guitar</span><span class="o">&gt;</span> <span class="n">guitar</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">getLogger</span><span class="o">().</span><span class="na">info</span><span class="o">(</span><span class="s">"Ordering new guitars..."</span><span class="o">);</span>
        
        <span class="c1">// ...</span>
        
        <span class="n">getLogger</span><span class="o">().</span><span class="na">info</span><span class="o">(</span><span class="s">"New guitars have been ordered, let's get to work!"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This improves application startup, but comes with a few drawbacks of its own:</p>

<ul>
  <li>All accesses to the <code class="language-plaintext highlighter-rouge">logger</code> field must go through the <code class="language-plaintext highlighter-rouge">getLogger</code> method, but code that fails to follow this practice runs the risk of encountering <code class="language-plaintext highlighter-rouge">NullPointerException</code>s;</li>
  <li>In multi-threaded environments, multiple logger objects could be created during concurrent calls to the <code class="language-plaintext highlighter-rouge">submitOrder</code> method;</li>
  <li><a href="https://en.wikipedia.org/wiki/Constant_folding">Constant-folding</a> access to an already-initialized <code class="language-plaintext highlighter-rouge">logger</code> field is no longer viable, as the JVM can’t trust its content never to change after its initial update.</li>
</ul>

<p>What we need is a solution that has the best of both worlds:</p>

<ul>
  <li>a way to promise that a field will be initialized by the time it is used;</li>
  <li>with a value that is computed at most once, and;</li>
  <li>safely with respect to concurrency.</li>
</ul>

<p>In other words, we want to <em>defer immutability</em>, and have first-class support for it in the Java runtime.</p>

<h5 id="lazy-constants">Lazy Constants</h5>

<p>JEP 526 introduces that first-class support in the form of <em>lazy constants</em>.
A lazy constant is an object of type <code class="language-plaintext highlighter-rouge">LazyConstant</code>, that holds a single data value.
It must be initialized some time before its content is first retrieved, and is immutable thereafter.</p>

<p>Let’s rewrite the <code class="language-plaintext highlighter-rouge">OrderController</code> class to use a lazy constant for its logger:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">OrderController</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">LazyConstant</span><span class="o">&lt;</span><span class="nc">Logger</span><span class="o">&gt;</span> <span class="n">logger</span> <span class="o">=</span> <span class="nc">LazyConstant</span><span class="o">.</span><span class="na">of</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="nc">Logger</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="nc">OrderController</span><span class="o">.</span><span class="na">class</span><span class="o">));</span>

    <span class="kt">void</span> <span class="nf">submitOrder</span><span class="o">(</span><span class="nc">User</span> <span class="n">user</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Guitar</span><span class="o">&gt;</span> <span class="n">guitar</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">logger</span><span class="o">.</span><span class="na">get</span><span class="o">().</span><span class="na">info</span><span class="o">(</span><span class="s">"Ordering new guitars..."</span><span class="o">);</span>
        
        <span class="c1">// ...</span>
        
        <span class="n">logger</span><span class="o">.</span><span class="na">get</span><span class="o">().</span><span class="na">info</span><span class="o">(</span><span class="s">"New guitars have been ordered, let's get to work!"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Initially, the lazy constant is uninitialized. When it is accessed for the first time through the <code class="language-plaintext highlighter-rouge">get()</code> method, it is initialized by invoking the lambda expression that was passed to the <code class="language-plaintext highlighter-rouge">of()</code> factory method.
If the lazy constant was already initialized, then the <code class="language-plaintext highlighter-rouge">get</code> method simply returns its content.
Thus, the <code class="language-plaintext highlighter-rouge">get</code> method guarantees that the provided lambda expression is evaluated only once (even when it is invoked concurrently).</p>

<p>If we look at the properties of lazy constants, we see that they fill a gap between final and non-final fields:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right"> </th>
      <th style="text-align: right"><strong>Update count</strong></th>
      <th style="text-align: right"><strong>Update location</strong></th>
      <th style="text-align: right"><strong>Constant folding?</strong></th>
      <th style="text-align: right"><strong>Concurrent updates?</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right"><code class="language-plaintext highlighter-rouge">final</code> field</td>
      <td style="text-align: right">1</td>
      <td style="text-align: right">Constructor or static initializer</td>
      <td style="text-align: right">Yes</td>
      <td style="text-align: right">No</td>
    </tr>
    <tr>
      <td style="text-align: right"><code class="language-plaintext highlighter-rouge">LazyConstant</code></td>
      <td style="text-align: right">[0, 1]</td>
      <td style="text-align: right">Computing function</td>
      <td style="text-align: right">Yes, after update</td>
      <td style="text-align: right">Yes, by winner</td>
    </tr>
    <tr>
      <td style="text-align: right">non-<code class="language-plaintext highlighter-rouge">final</code> field</td>
      <td style="text-align: right">[0, ∞]</td>
      <td style="text-align: right">Anywhere</td>
      <td style="text-align: right">No</td>
      <td style="text-align: right">Yes</td>
    </tr>
  </tbody>
</table>

<p>Usage of lazy constants is certainly not limited to loggers–we can also use a lazy constant to store the <code class="language-plaintext highlighter-rouge">OrderController</code> component itself, and related components:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">GuitarStore</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">LazyConstant</span><span class="o">&lt;</span><span class="nc">OrderController</span><span class="o">&gt;</span> <span class="no">ORDERS</span> <span class="o">=</span> <span class="nc">LazyConstant</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="nl">OrderController:</span><span class="o">:</span><span class="k">new</span><span class="o">);</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">LazyConstant</span><span class="o">&lt;</span><span class="nc">GuitarRepository</span><span class="o">&gt;</span> <span class="no">GUITARS</span> <span class="o">=</span> <span class="nc">LazyConstant</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="nl">GuitarRepository:</span><span class="o">:</span><span class="k">new</span><span class="o">);</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">LazyConstant</span><span class="o">&lt;</span><span class="nc">ManufacturerService</span><span class="o">&gt;</span> <span class="no">MANUFACTURERS</span> <span class="o">=</span> <span class="nc">LazyConstant</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="nl">ManufacturerService:</span><span class="o">:</span><span class="k">new</span><span class="o">);</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="nc">OrderController</span> <span class="nf">orders</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="no">ORDERS</span><span class="o">.</span><span class="na">get</span><span class="o">();</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="nc">GuitarRepository</span> <span class="nf">guitars</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="no">GUITARS</span><span class="o">.</span><span class="na">get</span><span class="o">();</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="nc">ManufacturerService</span> <span class="nf">manufacturers</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="no">MANUFACTURERS</span><span class="o">.</span><span class="na">get</span><span class="o">();</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The application’s startup time improves because it no longer initializes its components, such as <code class="language-plaintext highlighter-rouge">OrderController</code>, up front. 
Rather, it initializes each component on demand, via the <code class="language-plaintext highlighter-rouge">get</code> method of the corresponding lazy constant. 
Each component, moreover, initializes its sub-components, such as its logger, on demand in the same way.</p>

<p>Under the hood, the JVM will treat the content of any lazy constant that is declared as <code class="language-plaintext highlighter-rouge">final</code> as a constant, allowing constant-folding optimizations to happen.</p>

<h5 id="lazy-lists">Lazy Lists</h5>

<p>What if you wanted to keep track of multiple lazy constants, for example when keeping a pool of objects?
We can achieve this by using a <em>lazy list</em>:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">GuitarStore</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="kt">int</span> <span class="no">POOL_SIZE</span> <span class="o">=</span> <span class="mi">10</span><span class="o">;</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">OrderController</span><span class="o">&gt;</span> <span class="no">ORDERS</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">ofLazy</span><span class="o">(</span><span class="no">POOL_SIZE</span><span class="o">,</span> <span class="n">_</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nc">OrderController</span><span class="o">());</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="nc">OrderController</span> <span class="nf">orders</span><span class="o">()</span> <span class="o">{</span>
        <span class="kt">long</span> <span class="n">index</span> <span class="o">=</span> <span class="nc">Thread</span><span class="o">.</span><span class="na">currentThread</span><span class="o">().</span><span class="na">threadId</span><span class="o">()</span> <span class="o">%</span> <span class="no">POOL_SIZE</span><span class="o">;</span>
        <span class="k">return</span> <span class="no">ORDERS</span><span class="o">.</span><span class="na">get</span><span class="o">((</span><span class="kt">int</span><span class="o">)</span> <span class="n">index</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here, <code class="language-plaintext highlighter-rouge">ORDERS</code> is no longer a lazy constant, but a lazy list, in which each element is stored in a lazy constant.
To access the content, clients call <code class="language-plaintext highlighter-rouge">ORDERS.get(...)</code>, passing it an index, of which the first invocation will invoke the lambda function that ignores the index and invokes the <code class="language-plaintext highlighter-rouge">OrderController()</code> constructor.
Subsequent invocations of <code class="language-plaintext highlighter-rouge">ORDERS.get(...)</code> with the same index will return the element’s content immediately.</p>

<h5 id="lazy-maps">Lazy Maps</h5>

<p>Alternatively, we could have solved the problem with a <em>lazy map</em>, whose keys are known at construction time and whose values are stored in lazy constants, initialized on demand by a computing function that is also provided at construction:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">GuitarStore</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">OrderController</span><span class="o">&gt;</span> <span class="no">ORDERS</span> <span class="o">=</span> <span class="nc">Map</span><span class="o">.</span><span class="na">ofLazy</span><span class="o">(</span><span class="nc">Set</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"Customers"</span><span class="o">,</span> <span class="s">"Internal"</span><span class="o">,</span> <span class="s">"Testing"</span><span class="o">),</span> <span class="n">_</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nc">OrderController</span><span class="o">());</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="nc">OrderController</span> <span class="nf">orders</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="no">ORDERS</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="nc">Thread</span><span class="o">.</span><span class="na">currentThread</span><span class="o">().</span><span class="na">getName</span><span class="o">());</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>In this example, <code class="language-plaintext highlighter-rouge">OrderController</code> instances are associated with thread names (“Customers”, “Internal”, and “Testing” in this case) rather than integer indexes computed from thread identifiers. Lazy maps allow for more expressive access idioms than lazy lists, but otherwise have all the same benefits.</p>

<h4 id="whats-different-from-java-25-2">What’s Different From Java 25?</h4>

<p>The feature that used to be known as ‘stable values’ was renamed to ‘lazy constants’ to better capture its intended high-level use case.</p>

<p>Other changes have a similar purpose–they include:</p>
<ul>
  <li>Removing the low-level methods <code class="language-plaintext highlighter-rouge">orElseSet</code>, <code class="language-plaintext highlighter-rouge">setOrThrow</code>, and <code class="language-plaintext highlighter-rouge">trySet</code>, leaving only factory methods that take value-computing functions;</li>
  <li>Moving the factory methods for lazy lists (<code class="language-plaintext highlighter-rouge">StableValue.list</code>) and maps (<code class="language-plaintext highlighter-rouge">StableValue.map</code>) into the <code class="language-plaintext highlighter-rouge">List</code> and <code class="language-plaintext highlighter-rouge">Map</code> interfaces, respectively, to enhance discoverability;</li>
  <li>Incorporating the ideas behind ‘stable suppliers’ into the new <code class="language-plaintext highlighter-rouge">LazyConstant.get()</code> method;</li>
  <li>Removing the <code class="language-plaintext highlighter-rouge">function</code> and <code class="language-plaintext highlighter-rouge">intFunction</code> factory methods to further simplify the API;</li>
  <li>Disallowing <code class="language-plaintext highlighter-rouge">null</code> as a computed value in order to improve performance and better align lazy constants with constructs such as unmodifiable collections and scoped values.</li>
</ul>

<h4 id="more-information-5">More Information</h4>

<p><a href="https://openjdk.org/jeps/526">JEP 526</a> has more details on the current state of this feature, should you wish to learn more.</p>

<h3 id="jep-529-vector-api-eleventh-incubator">JEP 529: Vector API (Eleventh Incubator)</h3>

<p>The Vector API makes it possible to express vector computations that reliably compile at runtime to optimal vector instructions. 
This means that these computations will significantly outperform equivalent scalar computations on the supported CPU architectures (x64 and AArch64).</p>

<h4 id="vector-computations-help-me-out-here">Vector Computations? Help Me Out Here!</h4>

<p>A <em>vector computation</em> is a mathematical operation on one or more one-dimensional matrices of an arbitrary length. Think of a vector as an array with a dynamic length. Furthermore, the elements in the vector can be accessed in constant time via indices, just like with an array.</p>

<p>In the past, Java programmers could only program such computations at the assembly-code level. But now that modern CPUs support advanced <a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">SIMD</a> features (Single Instruction, Multiple Data), it becomes more important to take advantage of the performance gains that SIMD instructions and multiple lanes operating in parallel can bring. The Vector API brings that possibility closer to the Java programmer.</p>

<h4 id="code-example">Code Example</h4>

<p>Here is a code example (taken from the JEP) that compares a simple scalar computation over elements of arrays with its equivalent using the Vector API:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">scalarComputation</span><span class="o">(</span><span class="kt">float</span><span class="o">[]</span> <span class="n">a</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">b</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">c</span><span class="o">)</span> <span class="o">{</span>
   <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="n">c</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">+</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">])</span> <span class="o">*</span> <span class="o">-</span><span class="mf">1.0f</span><span class="o">;</span>
   <span class="o">}</span>
<span class="o">}</span>

<span class="kd">static</span> <span class="kd">final</span> <span class="nc">VectorSpecies</span><span class="o">&lt;</span><span class="nc">Float</span><span class="o">&gt;</span> <span class="no">SPECIES</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">SPECIES_PREFERRED</span><span class="o">;</span>

<span class="kt">void</span> <span class="nf">vectorComputation</span><span class="o">(</span><span class="kt">float</span><span class="o">[]</span> <span class="n">a</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">b</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">c</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
    <span class="kt">int</span> <span class="n">upperBound</span> <span class="o">=</span> <span class="no">SPECIES</span><span class="o">.</span><span class="na">loopBound</span><span class="o">(</span><span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">);</span>
    <span class="k">for</span> <span class="o">(;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">upperBound</span><span class="o">;</span> <span class="n">i</span> <span class="o">+=</span> <span class="no">SPECIES</span><span class="o">.</span><span class="na">length</span><span class="o">())</span> <span class="o">{</span>
        <span class="c1">// FloatVector va, vb, vc;</span>
        <span class="kt">var</span> <span class="n">va</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">fromArray</span><span class="o">(</span><span class="no">SPECIES</span><span class="o">,</span> <span class="n">a</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
        <span class="kt">var</span> <span class="n">vb</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">fromArray</span><span class="o">(</span><span class="no">SPECIES</span><span class="o">,</span> <span class="n">b</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
        <span class="kt">var</span> <span class="n">vc</span> <span class="o">=</span> <span class="n">va</span><span class="o">.</span><span class="na">mul</span><span class="o">(</span><span class="n">va</span><span class="o">)</span>
                   <span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">vb</span><span class="o">.</span><span class="na">mul</span><span class="o">(</span><span class="n">vb</span><span class="o">))</span>
                   <span class="o">.</span><span class="na">neg</span><span class="o">();</span>
        <span class="n">vc</span><span class="o">.</span><span class="na">intoArray</span><span class="o">(</span><span class="n">c</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">for</span> <span class="o">(;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="n">c</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">+</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">])</span> <span class="o">*</span> <span class="o">-</span><span class="mf">1.0f</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>From the perspective of the Java developer, this is just another way of expressing scalar computations. It might come across as being more verbose, but on the other hand it can bring spectacular performance gains.</p>

<h4 id="typical-use-cases">Typical Use Cases</h4>

<p>The Vector API provides a way to write complex vector algorithms in Java that perform extremely well, such as vectorized <code class="language-plaintext highlighter-rouge">hashCode</code> implementations or specialized array comparisons. Numerous domains can benefit from this, including machine learning, linear algebra, encryption, text processing, finance, and code within the JDK itself.</p>

<h4 id="whats-different-from-java-25-3">What’s Different From Java 25?</h4>

<p>Compared to the tenth incubator version of this feature in Java 25, nothing was changed or added.</p>

<p>The Vector API will keep incubating until necessary features of Project Valhalla become available as preview features. When that happens, the Vector API will be adapted to use them, and it will be promoted from incubation to preview.</p>

<h4 id="more-information-6">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/529">JEP 529</a>.</p>

<h3 id="jep-530-primitive-types-in-patterns-instanceof-and-switch-fourth-preview">JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview)</h3>

<p>Since Java 23, pattern matching supports primitive types in all pattern contexts, and in the <code class="language-plaintext highlighter-rouge">instanceof</code> and <code class="language-plaintext highlighter-rouge">switch</code> constructs. The feature has been in three consecutive preview statuses, and will be previewed for a fourth time in Java 26. Let’s first go through the differences with Java 22 before we highlight the changes in the fourth preview.</p>

<h4 id="pattern-matching-for-switch">Pattern Matching for Switch</h4>

<p>Java 22’s version of <a href="https://openjdk.org/jeps/441">pattern matching for switch</a> didn’t support type patterns that specify a primitive type. In Java 23 support was added for primitive type patterns in <code class="language-plaintext highlighter-rouge">switch</code>, allowing the following code example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">switch</span> <span class="o">(</span><span class="n">reverb</span><span class="o">.</span><span class="na">roomSize</span><span class="o">())</span> <span class="o">{</span>
    <span class="k">case</span> <span class="mi">1</span> <span class="o">-&gt;</span> <span class="s">"Toilet"</span><span class="o">;</span>
    <span class="k">case</span> <span class="mi">2</span> <span class="o">-&gt;</span> <span class="s">"Bedroom"</span><span class="o">;</span>
    <span class="k">case</span> <span class="mi">30</span> <span class="o">-&gt;</span> <span class="s">"Classroom"</span><span class="o">;</span>
    <span class="k">default</span> <span class="o">-&gt;</span> <span class="s">"Unsupported value: "</span> <span class="o">+</span> <span class="n">reverb</span><span class="o">.</span><span class="na">roomSize</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>

<p>…to be written as follows:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">switch</span> <span class="o">(</span><span class="n">reverb</span><span class="o">.</span><span class="na">roomSize</span><span class="o">())</span> <span class="o">{</span>
    <span class="k">case</span> <span class="mi">1</span> <span class="o">-&gt;</span> <span class="s">"Toilet"</span><span class="o">;</span>
    <span class="k">case</span> <span class="mi">2</span> <span class="o">-&gt;</span> <span class="s">"Bedroom"</span><span class="o">;</span>
    <span class="k">case</span> <span class="mi">30</span> <span class="o">-&gt;</span> <span class="s">"Classroom"</span><span class="o">;</span>
    <span class="k">case</span> <span class="kt">int</span> <span class="n">i</span> <span class="o">-&gt;</span> <span class="s">"Unsupported int value: "</span> <span class="o">+</span> <span class="n">i</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This also allows guards to inspect the matched value, like so:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">switch</span> <span class="o">(</span><span class="n">reverb</span><span class="o">.</span><span class="na">roomSize</span><span class="o">())</span> <span class="o">{</span>
    <span class="k">case</span> <span class="mi">1</span> <span class="o">-&gt;</span> <span class="s">"Toilet"</span><span class="o">;</span>
    <span class="k">case</span> <span class="mi">2</span> <span class="o">-&gt;</span> <span class="s">"Bedroom"</span><span class="o">;</span>
    <span class="k">case</span> <span class="mi">30</span> <span class="o">-&gt;</span> <span class="s">"Classroom"</span><span class="o">;</span>
    <span class="k">case</span> <span class="kt">int</span> <span class="n">i</span> <span class="n">when</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="mi">100</span> <span class="o">&amp;&amp;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">1000</span> <span class="o">-&gt;</span> <span class="s">"Cinema"</span><span class="o">;</span>
    <span class="k">case</span> <span class="kt">int</span> <span class="n">i</span> <span class="n">when</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="mi">5000</span> <span class="o">-&gt;</span> <span class="s">"Stadium"</span><span class="o">;</span>
    <span class="k">case</span> <span class="kt">int</span> <span class="n">i</span> <span class="o">-&gt;</span> <span class="s">"Unsupported int value: "</span> <span class="o">+</span> <span class="n">i</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<h4 id="record-patterns">Record Patterns</h4>

<p><a href="https://openjdk.org/jeps/440">Record patterns</a> used to have limited support for primitive types.
Recall that a record pattern decomposes a record into its individual components, but when one of them is a primitive type, the record pattern must be precise about its type. To illustrate this point, consider the following code example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">record</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">double</span> <span class="n">pitchInHz</span><span class="o">)</span> <span class="kd">implements</span> <span class="nc">Effect</span> <span class="o">{}</span>

<span class="kt">var</span> <span class="n">tuner</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Tuner</span><span class="o">(</span><span class="mi">440</span><span class="o">);</span> <span class="c1">// int argument is widened to double</span>

<span class="c1">// Attempt 1: record pattern match on int argument</span>
<span class="k">if</span> <span class="o">(</span><span class="n">tuner</span> <span class="k">instanceof</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">int</span> <span class="n">p</span><span class="o">))</span> <span class="o">{}</span> <span class="c1">// doesn't compile!</span>

<span class="c1">// Attempt 2: record pattern match on double argument</span>
<span class="k">if</span> <span class="o">(</span><span class="n">tuner</span> <span class="k">instanceof</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">double</span> <span class="n">p</span><span class="o">))</span> <span class="o">{</span>
    <span class="kt">int</span> <span class="n">pitch</span> <span class="o">=</span> <span class="n">p</span><span class="o">;</span> <span class="c1">// doesn't compile! needs a cast to int</span>
<span class="o">}</span>

<span class="c1">// Attempt 3: record pattern match on double argument, cast to int</span>
<span class="k">if</span> <span class="o">(</span><span class="n">tuner</span> <span class="k">instanceof</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">double</span> <span class="n">p</span><span class="o">))</span> <span class="o">{</span>
    <span class="kt">int</span> <span class="n">pitch</span> <span class="o">=</span> <span class="o">(</span><span class="kt">int</span><span class="o">)</span> <span class="n">p</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<p>To put it differently, the Java compiler widens the provided <code class="language-plaintext highlighter-rouge">int</code> to a <code class="language-plaintext highlighter-rouge">double</code>, but it doesn’t narrow it back to an <code class="language-plaintext highlighter-rouge">int</code>. This limitation exists because narrowing could lead to data loss: the value of the <code class="language-plaintext highlighter-rouge">double</code> at runtime might exceed the range of an <code class="language-plaintext highlighter-rouge">int</code> or have more precision than an <code class="language-plaintext highlighter-rouge">int</code> can accommodate. However, one significant advantage of pattern matching is its ability to automatically reject invalid values by not matching them at all. If the <code class="language-plaintext highlighter-rouge">double</code> component of a <code class="language-plaintext highlighter-rouge">Tuner</code> is either too large or too precise to safely convert back to an <code class="language-plaintext highlighter-rouge">int</code>, then <code class="language-plaintext highlighter-rouge">instanceof Tuner(int p)</code> would simply return <code class="language-plaintext highlighter-rouge">false</code>, allowing the program to manage the large <code class="language-plaintext highlighter-rouge">double</code> component in a different code branch.</p>

<p>This is analogous to how pattern matching currently behaves for reference type patterns. For example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">record</span> <span class="nf">SingleEffect</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">)</span> <span class="o">{}</span>
<span class="kt">var</span> <span class="n">singleEffect</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SingleEffect</span><span class="o">(...);</span>

<span class="k">if</span> <span class="o">(</span><span class="n">singleEffect</span> <span class="k">instanceof</span> <span class="nf">SingleEffect</span><span class="o">(</span><span class="nc">Delay</span> <span class="n">d</span><span class="o">))</span> <span class="o">{</span>
    <span class="c1">// ...</span>
<span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">singleEffect</span> <span class="k">instanceof</span> <span class="nf">SingleEffect</span><span class="o">(</span><span class="nc">Reverb</span> <span class="n">r</span><span class="o">))</span> <span class="o">{</span>
    <span class="c1">// ...</span>
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
    <span class="c1">// ...</span>
<span class="o">}</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">instanceof</code> can be used here to try to match a <code class="language-plaintext highlighter-rouge">SingleEffect</code> with a <code class="language-plaintext highlighter-rouge">Delay</code> or a <code class="language-plaintext highlighter-rouge">Reverb</code> component; it automatically narrows if the pattern matches.</p>

<p>To summarize, the JEP proposes to make primitive type patterns work as smoothly as reference type patterns, allowing <code class="language-plaintext highlighter-rouge">Tuner(int p)</code> even if the corresponding record component is a numeric primitive type other than <code class="language-plaintext highlighter-rouge">int</code>.</p>

<h4 id="pattern-matching-for-instanceof">Pattern Matching for instanceof</h4>

<p>The Java 22-version of <a href="https://openjdk.org/jeps/394">pattern matching for instanceof</a> didn’t support primitive type patterns, but this capability would perfectly align with the purpose of <code class="language-plaintext highlighter-rouge">instanceof</code>: to test whether a value can be converted safely to a given type. To convert primitives safely, Java developers had to deal with lossy casts and range checks to prevent loss of information:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">roomSize</span> <span class="o">=</span> <span class="n">reverb</span><span class="o">.</span><span class="na">roomSize</span><span class="o">();</span>

<span class="k">if</span> <span class="o">(</span><span class="n">roomSize</span> <span class="o">&gt;=</span> <span class="o">-</span><span class="mi">128</span> <span class="o">&amp;&amp;</span> <span class="n">roomSize</span> <span class="o">&lt;</span> <span class="mi">127</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">byte</span> <span class="n">r</span> <span class="o">=</span> <span class="o">(</span><span class="kt">byte</span><span class="o">)</span> <span class="n">roomSize</span><span class="o">;</span>
    <span class="c1">// now it's safe to use r</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The JEP proposes the possibility to replace these constructs with simple <code class="language-plaintext highlighter-rouge">instanceof</code> checks that operate on primitives. Let’s rewrite the code example to make use of this feature:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">roomSize</span> <span class="o">=</span> <span class="n">reverb</span><span class="o">.</span><span class="na">roomSize</span><span class="o">();</span>

<span class="k">if</span> <span class="o">(</span><span class="n">roomSize</span> <span class="k">instanceof</span> <span class="kt">byte</span> <span class="n">r</span><span class="o">)</span> <span class="o">{</span>
    <span class="c1">// now it's safe to use r</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The pattern <code class="language-plaintext highlighter-rouge">roomSize instanceof byte r</code> will match only if <code class="language-plaintext highlighter-rouge">roomSize</code> fits into a <code class="language-plaintext highlighter-rouge">byte</code>, eliminating the need for casts and range checks.</p>

<h4 id="primitive-types-in-instanceof">Primitive Types in instanceof</h4>

<p>The <code class="language-plaintext highlighter-rouge">instanceof</code> keyword used to take a reference type only, and since Java 16 it can also take a type pattern.
But it would make sense to have <code class="language-plaintext highlighter-rouge">instanceof</code> take a primitive type also.
In that case <code class="language-plaintext highlighter-rouge">instanceof</code> would check if the conversion is safe but would not actually perform it:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="o">(</span><span class="n">roomSize</span> <span class="k">instanceof</span> <span class="kt">byte</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// check if value of roomSize fits in a byte</span>
    <span class="o">...</span> <span class="o">(</span><span class="kt">byte</span><span class="o">)</span> <span class="n">roomSize</span> <span class="o">...</span> <span class="c1">// yes, it fits! but cast is required</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The JEP proposes to support this construct, which makes it easier to change the <code class="language-plaintext highlighter-rouge">instanceof</code> check to take a type pattern and vice versa.</p>

<h4 id="primitive-types-in-switch">Primitive Types in switch</h4>

<p>The Java 22-version of the <code class="language-plaintext highlighter-rouge">switch</code> statement/expression supported <code class="language-plaintext highlighter-rouge">byte</code>, <code class="language-plaintext highlighter-rouge">short</code>, <code class="language-plaintext highlighter-rouge">char</code>, and <code class="language-plaintext highlighter-rouge">int</code> values.
The JEP proposes to also add support for the other primitive types: <code class="language-plaintext highlighter-rouge">boolean</code>, <code class="language-plaintext highlighter-rouge">float</code>, <code class="language-plaintext highlighter-rouge">double</code> and <code class="language-plaintext highlighter-rouge">long</code>.
A <code class="language-plaintext highlighter-rouge">switch</code> on a <code class="language-plaintext highlighter-rouge">boolean</code> value can be a good alternative for the ternary operator (<code class="language-plaintext highlighter-rouge">?:</code>), because its branches can also hold statements instead of just expressions.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">guitaristResponse</span> <span class="o">=</span> <span class="k">switch</span> <span class="o">(</span><span class="n">guitar</span><span class="o">.</span><span class="na">isInTune</span><span class="o">())</span> <span class="o">{</span>
    <span class="k">case</span> <span class="kc">true</span> <span class="o">-&gt;</span> <span class="s">"Ready to play a song."</span><span class="o">;</span>
    <span class="k">case</span> <span class="kc">false</span> <span class="o">-&gt;</span> <span class="o">{</span>
        <span class="n">log</span><span class="o">.</span><span class="na">warn</span><span class="o">(</span><span class="s">"Guitar is out of tune!"</span><span class="o">);</span>
        <span class="n">yield</span> <span class="s">"Let's take five!"</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<h4 id="whats-different-from-java-25-4">What’s Different From Java 25?</h4>

<p>One minor change was made compared to Java 25: tighter dominance checks in <code class="language-plaintext highlighter-rouge">switch</code> constructs were applied.
One pattern is said to <em>dominate</em> another pattern if it matches all the values that the other pattern matches.
The definition of <a href="https://openjdk.org/jeps/441#Dominance-of-case-labels">dominance</a> used to be applicable to reference types only; this JEP broadens that definition so that primitive types are included as well.
As a result, e.g., the type pattern <code class="language-plaintext highlighter-rouge">long q</code> is now said to dominate the type pattern <code class="language-plaintext highlighter-rouge">int i</code>.</p>

<h4 id="preview-warning-2">Preview Warning</h4>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-7">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/530">JEP 530</a>.</p>

<h2 id="deprecations">Deprecations</h2>

<p>Java 26 also deprecates a few older features. Let’s see which ones were involved in this effort to improve stability and clarity.</p>

<h3 id="jep-500-prepare-to-make-final-mean-final">JEP 500: Prepare to Make Final Mean Final</h3>

<p>Final fields in Java represent immutable state. Once assigned in a constructor or in a class initializer, a final field cannot be reassigned. This behaviour is important when reasoning about correctness, and for performance reasons. The more constraints there are on the behaviour of a class, the more optimizations the JVM can apply (like <a href="https://en.wikipedia.org/wiki/Constant_folding">constant folding</a>). Moreover, the immutability we can expect from final fields plays an important role in the <a href="https://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#finalWrong">safe initialization of objects</a> in multi-threaded code.</p>

<p>Unfortunately, the expectation that a final field cannot be reassigned is false. <a href="https://openjdk.org/jeps/8305968#Undermining-integrity">Several APIs</a> allow final fields to be reassigned at any time by any code in a program, undermining all reasoning about correctness and invalidating important optimizations. The <em>deep reflection API</em> is the most notorious of them, through its <code class="language-plaintext highlighter-rouge">Field.setAccessible</code> and <code class="language-plaintext highlighter-rouge">Field.set</code> methods. These methods allow you to mutate final fields at will, for example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// A normal class with a final field</span>
<span class="kd">static</span> <span class="kd">class</span> <span class="nc">Guitar</span> <span class="o">{</span>
    <span class="kd">final</span> <span class="kt">int</span> <span class="n">numberOfStrings</span><span class="o">;</span>

    <span class="nc">Guitar</span><span class="o">()</span> <span class="o">{</span>
        <span class="n">numberOfStrings</span> <span class="o">=</span> <span class="mi">6</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kt">void</span> <span class="nf">main</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">ReflectiveOperationException</span> <span class="o">{</span>
    <span class="c1">// 1. Perform deep reflection over the final field in Guitar</span>
    <span class="n">java</span><span class="o">.</span><span class="na">lang</span><span class="o">.</span><span class="na">reflect</span><span class="o">.</span><span class="na">Field</span> <span class="n">numberOfStrings</span> <span class="o">=</span> <span class="nc">Guitar</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getDeclaredField</span><span class="o">(</span><span class="s">"numberOfStrings"</span><span class="o">);</span>
    <span class="n">numberOfStrings</span><span class="o">.</span><span class="na">setAccessible</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>      <span class="c1">// Make Guitar's final field mutable</span>

    <span class="c1">// 2. Create an instance of Guitar</span>
    <span class="nc">Guitar</span> <span class="n">guitar</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Guitar</span><span class="o">();</span>
    <span class="no">IO</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">guitar</span><span class="o">.</span><span class="na">numberOfStrings</span><span class="o">);</span>  <span class="c1">// Prints 6</span>

    <span class="c1">// 3. Mutate the final field in the object</span>
    <span class="n">numberOfStrings</span><span class="o">.</span><span class="na">set</span><span class="o">(</span><span class="n">guitar</span><span class="o">,</span> <span class="mi">12</span><span class="o">);</span>
    <span class="no">IO</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">guitar</span><span class="o">.</span><span class="na">numberOfStrings</span><span class="o">);</span>  <span class="c1">// Prints 12</span>
    <span class="n">numberOfStrings</span><span class="o">.</span><span class="na">set</span><span class="o">(</span><span class="n">guitar</span><span class="o">,</span> <span class="mi">4</span><span class="o">);</span>
    <span class="no">IO</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">guitar</span><span class="o">.</span><span class="na">numberOfStrings</span><span class="o">);</span>  <span class="c1">// Prints 4</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This example shows that, in practice, final fields can be as mutable as non-final fields.</p>

<h5 id="reasons-for-mutating-a-final-field">Reasons For Mutating a Final Field</h5>

<p>So why was the possibility added in the first place? The answer has to do with (you guessed it!) <em>serialization</em>. Serialization libraries need the ability to mutate final fields when initializing objects during deserialization. The problem is that relative little code mutates final fields for the right reasons, yet the mere existence of APIs for doing so makes it impossible to trust the value of any final field. Looking back, offering this functionality was a poor choice because it sacrifices integrity.</p>

<p>Recent additions like <a href="https://openjdk.org/jeps/371">hidden classes</a> and <a href="https://openjdk.org/jeps/395">records</a> don’t allow mutating final fields, and now it’s time to extend this behaviour to regular classes.</p>

<h5 id="final-field-restrictions">Final Field Restrictions</h5>

<p>JEP 500 proposes to issue warnings when deep reflection is used to mutate final fields. These warnings will prepare developers for a future release that ensures integrity by default by restricting final field mutation, making Java programs safer and potentially faster. One exception to this rule will remain supported, namely serialization libraries that need to mutate final fields during deserialization, via a limited-purpose API.</p>

<p>The effects of these <em>final field restrictions</em> will be strengthened over time. Rather than issue warnings, a future JDK release will, by default, throw exceptions when Java code uses deep reflection to mutate final fields.</p>

<h5 id="enabling-final-field-mutation">Enabling Final Field Mutation</h5>

<p>Application developers can avoid these warnings and expections by opting-in to final field mutation via the command-line. To achieve this, specify the <code class="language-plaintext highlighter-rouge">--enable-final-field-mutation</code> command-line option and pass it a comma-separated list of module names:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">--enable-final-field-mutation</span><span class="o">=</span>module1,module2
</code></pre></div></div>

<p>Additional techniques are also available, such as setting environment variables, adding it to a JAR’s manifest or configuring it in a custom runtime using <code class="language-plaintext highlighter-rouge">jlink</code>. Refer to <a href="https://openjdk.org/jeps/500">JEP 500</a> for more details on these techniques.</p>

<h5 id="behaviour-of-fieldset">Behaviour of Field::set</h5>

<p>In JDK 26 the rules for <code class="language-plaintext highlighter-rouge">Field::set</code> on a <code class="language-plaintext highlighter-rouge">final</code> field change. The field will be mutated only if:</p>

<ol>
  <li><code class="language-plaintext highlighter-rouge">f.setAccessible(true)</code> has already succeeded,</li>
  <li>the field’s declaring class is in a package <strong>open</strong> to the caller’s module, and</li>
  <li>final‑field mutation is enabled for that module.</li>
</ol>

<p>The last two conditions are new. Consequently:</p>

<ul>
  <li>
    <p>If a module doesn’t have final‑field mutation enabled, any attempt to change a <code class="language-plaintext highlighter-rouge">final</code> field via deep reflection throws an <code class="language-plaintext highlighter-rouge">IllegalAccessException</code> (unless the JVM is started with <code class="language-plaintext highlighter-rouge">--illegal-final-field-mutation</code>). <code class="language-plaintext highlighter-rouge">f.setAccessible(true)</code> may still succeed, but <code class="language-plaintext highlighter-rouge">f.set(...)</code> is illegal.</p>
  </li>
  <li>
    <p>If final‑field mutation is enabled but the field’s package isn’t open to the module, the same exception is thrown. This can happen when module A (with an open package) calls <code class="language-plaintext highlighter-rouge">f.setAccessible(true)</code> and passes the <code class="language-plaintext highlighter-rouge">Field</code> to module B, which has mutation enabled but no access to the package; module B’s <code class="language-plaintext highlighter-rouge">f.set(...)</code> is illegal.</p>
  </li>
</ul>

<h5 id="effects-on-serialization-libraries">Effects On Serialization Libraries</h5>

<p>When future JDK releases tighten final‑field restrictions, serialization libraries won’t be able to rely on deep reflection automatically. Instead of asking users to turn on final‑field mutation via command‑line flags, library maintainers should use the <code class="language-plaintext highlighter-rouge">sun.reflect.ReflectionFactory</code> API, which is intended for this purpose. This API lets a serialization library acquire a method handle to special JDK‑generated code that can initialize an object by directly writing to its instance fields, even if they’re declared <code class="language-plaintext highlighter-rouge">final</code>. The generated code gives the library the same capabilities as the JDK’s built‑in serialization mechanisms, eliminating the need to enable final‑field mutation for the library’s module.</p>

<blockquote>
  <p>Note that <code class="language-plaintext highlighter-rouge">sun.reflect.ReflectionFactory</code> only works for deserializing classes that implement <code class="language-plaintext highlighter-rouge">java.io.Serializable</code>.</p>
</blockquote>

<h5 id="libraries-and-frameworks-should-not-use-deep-reflection-to-mutate-final-fields">Libraries and Frameworks Should Not Use Deep Reflection to Mutate Final Fields</h5>

<p>Some dependency‑injection, testing, and mocking libraries rely on deep reflection to tamper with objects, even changing final fields. Their maintainers should treat enabling final‑field mutation via command‑line switches as a fallback only. Preferably, they should adopt designs that eliminate the need to alter final or private fields. For instance, most DI frameworks prohibit injecting final fields already and encourage constructor injection instead.</p>

<h4 id="more-information-8">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/500">JEP 500</a>.</p>

<h3 id="jep-504-remove-the-applet-api">JEP 504: Remove the Applet API</h3>

<p>When the Java Platform rose to fame in the late 1990s and early 2000s, one of its main catalysts were Java applets and the Applet API. Java applets were small Java programs that could be embedded in web pages and run in a web browser, allowing developers to create interactive web applications. They were widely used for things like games, animations, and other interactive content on the web. People who weren’t Java programmers at all at least knew the name ‘Java’ from their browser because of applets! (in roughly the same way as kids these days know about Java’s existence because of a game called Minecraft.)</p>

<p><img src="/assets/images/blog/java-applet.png" alt="Hello! I am an applet!" /></p>

<p>However, over time, Java applets became less popular due to security concerns and the rise of alternative technologies such as JavaScript and HTML5. As a result, many browser vendors have removed support for them. This is why the Applet API <a href="https://openjdk.org/jeps/289">was deprecated in Java 9</a>, <a href="https://openjdk.org/jeps/398">deprecated for removal in Java 17</a> and it’s one of the reasons why it will be removed in its entirety in Java 26. On top of that, a necessary foundation for running applets by sandboxing untrusted code, the Security Manager, <a href="https://openjdk.org/jeps/486">was permanently disabled in Java 24</a>, providing another reason to finally sunset the Applet API.</p>

<h5 id="removals">Removals</h5>

<p>The following elements will be removed:</p>

<ul>
  <li>The entire <code class="language-plaintext highlighter-rouge">java.applet</code> package, consisting of:
    <ul>
      <li><code class="language-plaintext highlighter-rouge">java.applet.Applet</code></li>
      <li><code class="language-plaintext highlighter-rouge">java.applet.AppletContext</code></li>
      <li><code class="language-plaintext highlighter-rouge">java.applet.AppletStub</code></li>
      <li><code class="language-plaintext highlighter-rouge">java.applet.AudioClip</code></li>
    </ul>
  </li>
  <li>These additional classes:
    <ul>
      <li><code class="language-plaintext highlighter-rouge">java.beans.AppletInitializer</code></li>
      <li><code class="language-plaintext highlighter-rouge">javax.swing.JApplet</code></li>
    </ul>
  </li>
  <li>Any remaining API elements that reference the above classes and interfaces, including methods and fields in:
    <ul>
      <li><code class="language-plaintext highlighter-rouge">java.beans.Beans</code></li>
      <li><code class="language-plaintext highlighter-rouge">javax.swing.RepaintManager</code></li>
    </ul>
  </li>
</ul>

<h5 id="risks--migration">Risks &amp; Migration</h5>

<p>Given that the Applet API in its current form is largely unusable, there is no substantial risk to user applications in removing the API. Applications that still use the Applet API will either stay on older releases or will migrate to some other API, like the AWT API or the <a href="https://docs.oracle.com/en/java/javase/25/docs/api/java.desktop/javax/sound/SoundClip.html"><code class="language-plaintext highlighter-rouge">javax.sound.SoundClip</code></a> class for audio playback.</p>

<h4 id="more-information-9">More Information</h4>

<p>For more information on this removal, read <a href="https://openjdk.org/jeps/504">JEP 504</a>.</p>

<h2 id="final-thoughts">Final thoughts</h2>

<p>And that concludes our discussion of the 10 JEPs that come with Java 26. But that’s not even all that’s new: <a href="https://jdk.java.net/26/release-notes">many other updates</a> were included in this release, including various performance, stability and security updates. One thing is for sure: this version of Java is primed and ready for more additions later this year. So what are you waiting for? It’s time to take this brand-new Java release for a spin!</p>]]></content><author><name>Hanno Embregts</name></author><category term="java" /><summary type="html"><![CDATA[Java 26 is here, and its main purpose seems to be to provide a solid foundation for future things to come. It comes with a few new features, some performance improvements and multiple enhancements that mention Project Valhalla as the inspiration for their existence. This post has all the info!]]></summary></entry><entry><title type="html">Here’s Java 25, Ready to Perform to the Limit</title><link href="https://hanno.codes/2025/09/16/heres-java-25/" rel="alternate" type="text/html" title="Here’s Java 25, Ready to Perform to the Limit" /><published>2025-09-16T02:30:00+00:00</published><updated>2025-09-16T02:30:00+00:00</updated><id>https://hanno.codes/2025/09/16/heres-java-25</id><content type="html" xml:base="https://hanno.codes/2025/09/16/heres-java-25/"><![CDATA[<p>It’s been six months since Java 24 was released, so it’s time for a fresh set of new Java features. 
And the feature that immediately grabs the attention this time is <em>stable values</em>, taking Java’s support of immutability to the next level.
Also, Java’s focus on improving performance intensifies, as more JEPs emerge from Project Leyden. 
On top of that, the Java Flight Recorder is now more equipped than ever to tackle performance issues!</p>

<p>This post takes you on a tour of everything that is part of this release, giving you a brief introduction to each of them. 
Where applicable the differences with Java 24 are highlighted and a few typical use cases are provided, so that you’ll be more than ready to start using these features after reading this.</p>

<p><img src="/assets/images/blog/performance.jpg" alt="Performance" /></p>
<blockquote>
  <p>Photo from <a href="https://pxhere.com/en/photo/1023487">PxHere</a></p>
</blockquote>

<blockquote>
  <p>Short descriptions of the repreviewed and finalized features are provided to prevent this article from becoming too lengthy. Each of these features comes with a link to a longer description should you wish to learn more.</p>
</blockquote>

<h2 id="jep-overview">JEP Overview</h2>

<p>To start off, let’s look at an overview of the JEPs that ship with Java 25. This table contains the preview status for all JEP’s, to which project they belong, what kind of features they add and the things that have changed since Java 24.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right"><strong>JEP</strong></th>
      <th><strong>Title</strong></th>
      <th style="text-align: right"><strong>Status</strong></th>
      <th style="text-align: right"><strong>Project</strong></th>
      <th style="text-align: right"><strong>Feature Type</strong></th>
      <th style="text-align: right"><strong>Changes since Java 24</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-470-pem-encodings-of-cryptographic-objects-preview">470</a></strong></td>
      <td>PEM Encodings of Cryptographic Objects</td>
      <td style="text-align: right">Preview</td>
      <td style="text-align: right">Security Libs</td>
      <td style="text-align: right">Security</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-502-stable-values-preview">502</a></strong></td>
      <td>Stable Values</td>
      <td style="text-align: right">Preview</td>
      <td style="text-align: right">Core Libs</td>
      <td style="text-align: right">New API</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-503-remove-the-32-bit-x86-port">503</a></strong></td>
      <td>Remove the 32-bit x86 Port</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">HotSpot</td>
      <td style="text-align: right">Deprecation</td>
      <td style="text-align: right">Removal</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-505-structured-concurrency-fifth-preview">505</a></strong></td>
      <td>Structured Concurrency</td>
      <td style="text-align: right">Fifth Preview</td>
      <td style="text-align: right">Loom</td>
      <td style="text-align: right">Concurrency</td>
      <td style="text-align: right">Major</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-506-scoped-values">506</a></strong></td>
      <td>Scoped Values</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Loom</td>
      <td style="text-align: right">Concurrency</td>
      <td style="text-align: right">Minor</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-507-primitive-types-in-patterns-instanceof-and-switch-third-preview">507</a></strong></td>
      <td>Primitive Types in Patterns, instanceof, and switch</td>
      <td style="text-align: right">Third Preview</td>
      <td style="text-align: right">Amber</td>
      <td style="text-align: right">Language</td>
      <td style="text-align: right">None</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-508-vector-api-tenth-incubator">508</a></strong></td>
      <td>Vector API</td>
      <td style="text-align: right">Tenth Incubator</td>
      <td style="text-align: right">Panama</td>
      <td style="text-align: right">New API</td>
      <td style="text-align: right">Minor</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-509-jfr-cpu-time-profiling-experimental">509</a></strong></td>
      <td>JFR CPU-Time Profiling</td>
      <td style="text-align: right">Experimental</td>
      <td style="text-align: right">HotSpot / JFR</td>
      <td style="text-align: right">Profiling</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-510-key-derivation-function-api">510</a></strong></td>
      <td>Key Derivation Function API</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Security Libs</td>
      <td style="text-align: right">Security</td>
      <td style="text-align: right">None</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-511-module-import-declarations">511</a></strong></td>
      <td>Module Import Declarations</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Amber</td>
      <td style="text-align: right">Language</td>
      <td style="text-align: right">None</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-512-compact-source-files-and-instance-main-methods">512</a></strong></td>
      <td>Compact Source Files and Instance Main Methods</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Amber</td>
      <td style="text-align: right">Language</td>
      <td style="text-align: right">Major</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-513-flexible-constructor-bodies">513</a></strong></td>
      <td>Flexible Constructor Bodies</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Amber</td>
      <td style="text-align: right">Language</td>
      <td style="text-align: right">None</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-514-ahead-of-time-command-line-ergonomics">514</a></strong></td>
      <td>Ahead-of-Time Command-Line Ergonomics</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Leyden</td>
      <td style="text-align: right">Performance</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-515-ahead-of-time-method-profiling">515</a></strong></td>
      <td>Ahead-of-Time Method Profiling</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Leyden</td>
      <td style="text-align: right">Performance</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-518-jfr-cooperative-sampling">518</a></strong></td>
      <td>JFR Cooperative Sampling</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">HotSpot / JFR</td>
      <td style="text-align: right">Profiling</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-519-compact-object-headers">519</a></strong></td>
      <td>Compact Object Headers</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">HotSpot</td>
      <td style="text-align: right">Performance</td>
      <td style="text-align: right">None</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-520-jfr-method-timing--tracing">520</a></strong></td>
      <td>JFR Method Timing &amp; Tracing</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">HotSpot / JFR</td>
      <td style="text-align: right">Profiling</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong><a href="#jep-521-generational-shenandoah">521</a></strong></td>
      <td>Generational Shenandoah</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">HotSpot / GC</td>
      <td style="text-align: right">Performance</td>
      <td style="text-align: right">Stability and performance improvements</td>
    </tr>
  </tbody>
</table>

<h2 id="new-features">New features</h2>

<p>Let’s start with the JEP’s that add brand-new features to Java 25.</p>

<h3 id="core-libs">Core Libs</h3>

<p>Java 25 contains a single new feature that is part of the Core Libs:</p>

<ul>
  <li>Stable Values (Preview)</li>
</ul>

<h4 id="jep-502-stable-values-preview">JEP 502: Stable Values (Preview)</h4>

<p>Immutable objects are a far less complicated concept than mutable objects, because they can only be in a single state and can be shared freely across multiple threads.
Currently, the main tool to achieve immutability in Java is <code class="language-plaintext highlighter-rouge">final</code> fields.
But they come with two drawbacks, restricting their potential in many real-world applications:</p>

<ul>
  <li>they must be set eagerly;</li>
  <li>the order in which multiple <code class="language-plaintext highlighter-rouge">final</code> fields are initialized can never be changed, as it is determined by the <a href="https://docs.oracle.com/javase/specs/jls/se23/html/jls-12.html#jls-12.4">textual order</a> in which the fields are declared.</li>
</ul>

<p>Consider the use of immutability in the following code example, which takes place in a guitar store domain:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">OrderController</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">Logger</span> <span class="n">logger</span> <span class="o">=</span> <span class="nc">Logger</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="nc">OrderController</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>

    <span class="kt">void</span> <span class="nf">submitOrder</span><span class="o">(</span><span class="nc">User</span> <span class="n">user</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Guitar</span><span class="o">&gt;</span> <span class="n">guitar</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Ordering new guitars..."</span><span class="o">);</span>
        
        <span class="c1">// ...</span>
        
        <span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"New guitars have been ordered, let's get to work!"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Whenever an instance of <code class="language-plaintext highlighter-rouge">OrderController</code> is created, the <code class="language-plaintext highlighter-rouge">logger</code> field is initialized eagerly, which potentially makes creating an <code class="language-plaintext highlighter-rouge">OrderController</code> slow.
And this might not be the only place in our guitar store application where a <code class="language-plaintext highlighter-rouge">logger</code> field is being initialized eagerly:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">GuitarStore</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">OrderController</span> <span class="no">ORDERS</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">OrderController</span><span class="o">();</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">GuitarRepository</span> <span class="no">GUITARS</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">GuitarRepository</span><span class="o">();</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">ManufacturerService</span> <span class="no">MANUFACTURERS</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ManufacturerService</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>

<p>All this initialization work causes the application to start up more slowly, and the worst thing is: it may not even be necessary!
If a user is simply browsing the guitar store, with no intention of ordering a new guitar, the <code class="language-plaintext highlighter-rouge">OrderController</code> won’t even be called and we will have initialized the <code class="language-plaintext highlighter-rouge">logger</code> field for nothing.</p>

<h5 id="sacrificing-immutability-for-more-flexible-initialization">Sacrificing Immutability For More Flexible Initialization</h5>

<p>The only alternative we currently have is to resort to a mutability-based approach, in which we delay the initialization of complex objects to as late a time as possible:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">OrderController</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="nc">Logger</span> <span class="n">logger</span><span class="o">;</span>

    <span class="nc">Logger</span> <span class="nf">getLogger</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">logger</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">logger</span> <span class="o">=</span> <span class="nc">Logger</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="nc">OrderController</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
        <span class="o">}</span>
        <span class="k">return</span> <span class="n">logger</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kt">void</span> <span class="nf">submitOrder</span><span class="o">(</span><span class="nc">User</span> <span class="n">user</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Guitar</span><span class="o">&gt;</span> <span class="n">guitar</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">getLogger</span><span class="o">().</span><span class="na">info</span><span class="o">(</span><span class="s">"Ordering new guitars..."</span><span class="o">);</span>
        
        <span class="c1">// ...</span>
        
        <span class="n">getLogger</span><span class="o">().</span><span class="na">info</span><span class="o">(</span><span class="s">"New guitars have been ordered, let's get to work!"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This improves application startup, but comes with a few drawbacks of its own:</p>

<ul>
  <li>All accesses to the <code class="language-plaintext highlighter-rouge">logger</code> field must go through the <code class="language-plaintext highlighter-rouge">getLogger</code> method, but code that fails to follow this practice runs the risk of encountering <code class="language-plaintext highlighter-rouge">NullPointerException</code>s;</li>
  <li>In multi-threaded environments, multiple logger objects could be created during concurrent calls to the <code class="language-plaintext highlighter-rouge">submitOrder</code> method;</li>
  <li><a href="https://en.wikipedia.org/wiki/Constant_folding">Constant-folding</a> access to an already-initialized <code class="language-plaintext highlighter-rouge">logger</code> field is no longer viable, as the JVM can’t trust its content never to change after its initial update.</li>
</ul>

<p>What we need is a solution that has the best of both worlds:</p>

<ul>
  <li>a way to promise that a field will be initialized by the time it is used,</li>
  <li>with a value that is computed at most once, and</li>
  <li>safely with respect to concurrency.</li>
</ul>

<p>In other world, we want to <em>defer immutability</em>, and first-class support for it in the Java runtime.</p>

<h5 id="stable-values">Stable Values</h5>

<p>JEP 502 introduces that first-class support in the form of <em>stable values</em>.
A stable value is an object of type <code class="language-plaintext highlighter-rouge">StableValue</code>, that holds a single data value.
It must be initialized some time before its content is first retrieved, and it is immutable thereafter.</p>

<p>Let’s rewrite the <code class="language-plaintext highlighter-rouge">OrderController</code> class to use a stable value for its logger:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">OrderController</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">StableValue</span><span class="o">&lt;</span><span class="nc">Logger</span><span class="o">&gt;</span> <span class="n">logger</span> <span class="o">=</span> <span class="nc">StableValue</span><span class="o">.</span><span class="na">of</span><span class="o">();</span>

    <span class="nc">Logger</span> <span class="nf">getLogger</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">logger</span><span class="o">.</span><span class="na">orElseSet</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="nc">Logger</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="nc">OrderController</span><span class="o">.</span><span class="na">class</span><span class="o">));</span>
    <span class="o">}</span>

    <span class="kt">void</span> <span class="nf">submitOrder</span><span class="o">(</span><span class="nc">User</span> <span class="n">user</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Guitar</span><span class="o">&gt;</span> <span class="n">guitar</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">getLogger</span><span class="o">().</span><span class="na">info</span><span class="o">(</span><span class="s">"Ordering new guitars..."</span><span class="o">);</span>
        
        <span class="c1">// ...</span>
        
        <span class="n">getLogger</span><span class="o">().</span><span class="na">info</span><span class="o">(</span><span class="s">"New guitars have been ordered, let's get to work!"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>After the call to <code class="language-plaintext highlighter-rouge">StableValue.of()</code>, the stable value holds no content.
When it is accessed through the <code class="language-plaintext highlighter-rouge">getLogger()</code> method, <code class="language-plaintext highlighter-rouge">logger.orElseSet(...)</code> returns its content if the stable value was already set.
If it is unset, the <code class="language-plaintext highlighter-rouge">orElseSet</code> method initializes it with the value supplied by the lambda expression.
The <code class="language-plaintext highlighter-rouge">orElseSet</code> method also guarantees that the provided lambda expression is evaluated only once, even when it is invoked concurrently.</p>

<p>If we look at the properties of stable values, we see that they fill a gap between final and non-final fields:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right"> </th>
      <th style="text-align: right"><strong>Update count</strong></th>
      <th style="text-align: right"><strong>Update location</strong></th>
      <th style="text-align: right"><strong>Constant folding?</strong></th>
      <th style="text-align: right"><strong>Concurrent updates?</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">final field</td>
      <td style="text-align: right">1</td>
      <td style="text-align: right">Constructor or static initializer</td>
      <td style="text-align: right">Yes</td>
      <td style="text-align: right">No</td>
    </tr>
    <tr>
      <td style="text-align: right"><code class="language-plaintext highlighter-rouge">StableValue</code></td>
      <td style="text-align: right">[0, 1]</td>
      <td style="text-align: right">Constructor or static initializer</td>
      <td style="text-align: right">Yes, after update</td>
      <td style="text-align: right">Yes, by winner</td>
    </tr>
    <tr>
      <td style="text-align: right">non-final field</td>
      <td style="text-align: right">[0, ∞]</td>
      <td style="text-align: right">Anywhere</td>
      <td style="text-align: right">No</td>
      <td style="text-align: right">Yes</td>
    </tr>
  </tbody>
</table>

<p>Usage of stable values is certainly not limited to loggers–we can also use a stable value to store the <code class="language-plaintext highlighter-rouge">OrderController</code> component itself, and related components:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">GuitarStore</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">StableValue</span><span class="o">&lt;</span><span class="nc">OrderController</span><span class="o">&gt;</span> <span class="no">ORDERS</span> <span class="o">=</span> <span class="nc">StableValue</span><span class="o">.</span><span class="na">of</span><span class="o">();</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">StableValue</span><span class="o">&lt;</span><span class="nc">GuitarRepository</span><span class="o">&gt;</span> <span class="no">GUITARS</span> <span class="o">=</span> <span class="nc">StableValue</span><span class="o">.</span><span class="na">of</span><span class="o">();</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">StableValue</span><span class="o">&lt;</span><span class="nc">ManufacturerService</span><span class="o">&gt;</span> <span class="no">MANUFACTURERS</span> <span class="o">=</span> <span class="nc">StableValue</span><span class="o">.</span><span class="na">of</span><span class="o">();</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="nc">OrderController</span> <span class="nf">orders</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="no">ORDERS</span><span class="o">.</span><span class="na">orElseSet</span><span class="o">(</span><span class="nl">OrderController:</span><span class="o">:</span><span class="k">new</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="nc">GuitarRepository</span> <span class="nf">guitars</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="no">GUITARS</span><span class="o">.</span><span class="na">orElseSet</span><span class="o">(</span><span class="nl">GuitarRepository:</span><span class="o">:</span><span class="k">new</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="nc">ManufacturerService</span> <span class="nf">manufacturers</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="no">MANUFACTURERS</span><span class="o">.</span><span class="na">orElseSet</span><span class="o">(</span><span class="nl">ManufacturerService:</span><span class="o">:</span><span class="k">new</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The application’s startup time improves because it no longer initializes its components, such as <code class="language-plaintext highlighter-rouge">OrderController</code>, up front. 
Rather, it initializes each component on demand, via the <code class="language-plaintext highlighter-rouge">orElseSet</code> method of the corresponding stable value. 
Each component, moreover, initializes its sub-components, such as its logger, on demand in the same way.</p>

<p>Under the hood, the JVM will treat the content of any stable value that is declared as <code class="language-plaintext highlighter-rouge">final</code> as a constant, allowing constant-folding optimizations to happen.</p>

<h5 id="stable-suppliers">Stable Suppliers</h5>

<p>There’s one catch with our current approach: all access to the <code class="language-plaintext highlighter-rouge">logger</code> stable value must go through the <code class="language-plaintext highlighter-rouge">getLogger</code> method.
It would be more convenient if we could separate initializing a stable value from the actual initialization itself.
To this end, JEP 502 introduces <em>stable suppliers</em>, and this is how they work:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">OrderController</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Logger</span><span class="o">&gt;</span> <span class="n">logger</span> <span class="o">=</span> <span class="nc">StableValue</span><span class="o">.</span><span class="na">supplier</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="nc">Logger</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="nc">OrderController</span><span class="o">.</span><span class="na">class</span><span class="o">));</span>

    <span class="kt">void</span> <span class="nf">submitOrder</span><span class="o">(</span><span class="nc">User</span> <span class="n">user</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Guitar</span><span class="o">&gt;</span> <span class="n">guitar</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">logger</span><span class="o">.</span><span class="na">get</span><span class="o">().</span><span class="na">info</span><span class="o">(</span><span class="s">"Ordering new guitars..."</span><span class="o">);</span>
        
        <span class="c1">// ...</span>
        
        <span class="n">logger</span><span class="o">.</span><span class="na">get</span><span class="o">().</span><span class="na">info</span><span class="o">(</span><span class="s">"New guitars have been ordered, let's get to work!"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here, <code class="language-plaintext highlighter-rouge">logger</code> is no longer a stable value, but a stable <code class="language-plaintext highlighter-rouge">Supplier</code>. 
When a stable supplier is first created via <code class="language-plaintext highlighter-rouge">StableValue.supplier(...)</code>, the content of the underlying stable value is not yet initialized.
To access the logger, clients call <code class="language-plaintext highlighter-rouge">logger.get()</code>, of which the first invocation will invoke the supplier and use its result to initialize the stable value.
Subsequent invocations of <code class="language-plaintext highlighter-rouge">logger.get()</code> will return the content immediately.
The resulting code is arguably more readable, because we no longer need a separate <code class="language-plaintext highlighter-rouge">getLogger</code> method.</p>

<h5 id="stable-lists">Stable Lists</h5>

<p>What if you wanted to keep track of multiple stable values, for example when keeping a pool of objects?
We can achieve this by using a <em>stable list</em>:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">GuitarStore</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="kt">int</span> <span class="no">POOL_SIZE</span> <span class="o">=</span> <span class="mi">10</span><span class="o">;</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">OrderController</span><span class="o">&gt;</span> <span class="no">ORDERS</span> <span class="o">=</span> <span class="nc">StableValue</span><span class="o">.</span><span class="na">list</span><span class="o">(</span><span class="no">POOL_SIZE</span><span class="o">,</span> <span class="n">_</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nc">OrderController</span><span class="o">());</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="nc">OrderController</span> <span class="nf">orders</span><span class="o">()</span> <span class="o">{</span>
        <span class="kt">long</span> <span class="n">index</span> <span class="o">=</span> <span class="nc">Thread</span><span class="o">.</span><span class="na">currentThread</span><span class="o">().</span><span class="na">threadId</span><span class="o">()</span> <span class="o">%</span> <span class="no">POOL_SIZE</span><span class="o">;</span>
        <span class="k">return</span> <span class="no">ORDERS</span><span class="o">.</span><span class="na">get</span><span class="o">((</span><span class="kt">int</span><span class="o">)</span> <span class="n">index</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here, <code class="language-plaintext highlighter-rouge">ORDERS</code> is no longer a stable value, but a stable list, where each element is the content of an underlying stable value.
To access the content, clients call <code class="language-plaintext highlighter-rouge">ORDERS.get(...)</code>, passing it an index, of which the first invocation will invoke the lamdba function that ignores the index and invokes the <code class="language-plaintext highlighter-rouge">OrderController()</code> constructor.
Subsequent invocations of <code class="language-plaintext highlighter-rouge">ORDERS.get(...)</code> with the same index will return the element’s content immediately.</p>

<h5 id="preview-warning">Preview Warning</h5>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h5 id="more-information">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/502">JEP 502</a>.</p>

<h3 id="hotspot">HotSpot</h3>

<p>Java 25 introduces two new features in <a href="https://openjdk.org/groups/hotspot/">HotSpot</a>:</p>

<ul>
  <li>Ahead-of-Time Command-Line Ergonomics</li>
  <li>Ahead-of-Time Method Profiling</li>
</ul>

<blockquote>
  <p>The HotSpot JVM is the runtime engine that is developed by Oracle. It translates Java bytecode into machine code for the host operating system’s processor architecture.</p>
</blockquote>

<h4 id="jep-514-ahead-of-time-command-line-ergonomics">JEP 514: Ahead-of-Time Command-Line Ergonomics</h4>

<p>Java 24 introduced an <em>ahead-of-time cache</em> to store classes in after reading, parsing, loading and linking them.
A created cache for a specific application could then be re-used in subsequent runs of that application to improve startup time, by up to 42%.</p>

<p>In Java 24, creating such a cache took two runs of the <code class="language-plaintext highlighter-rouge">java</code> process. The first one (the ‘training run’) would record its AOT configuration into the file <code class="language-plaintext highlighter-rouge">app.aotconf</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:AOTMode<span class="o">=</span>record <span class="nt">-XX</span>:AOTConfiguration<span class="o">=</span>app.aotconf <span class="nt">-cp</span> app.jar com.example.App ...
</code></pre></div></div>

<p>…and the second one would use the configuration to create the cache into the file <code class="language-plaintext highlighter-rouge">app.aot</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:AOTMode<span class="o">=</span>create <span class="nt">-XX</span>:AOTConfiguration<span class="o">=</span>app.aotconf <span class="nt">-XX</span>:AOTCache<span class="o">=</span>app.aot <span class="nt">-cp</span> app.jar
</code></pre></div></div>

<p>But it’s a little inconvenient that creating the cache is currently a two-step process.
On top of that, the AOT configuration file just sits there after creation, and isn’t needed any more once the cache has been created.</p>

<p>So that’s why JEP 514 introduces the command-line option <code class="language-plaintext highlighter-rouge">AOTCacheOutput</code>, which performs a training run and creates an AOT cache in a single step.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:AOTCacheOutput<span class="o">=</span>app.aot <span class="nt">-cp</span> app.jar com.example.App ...
</code></pre></div></div>

<p>As a convenience, when operating in this way the JVM creates a temporary file for the AOT configuration, deleting it when finished.
A production run that uses the AOT cache is started the same way as before:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:AOTCache<span class="o">=</span>app.aot <span class="nt">-cp</span> app.jar com.example.App ...
</code></pre></div></div>

<p>For common cases this is a far more convenient way of creating AOT caches.
The ability to specify AOT modes and AOT configurations will be retained to support uncommon cases.</p>

<h5 id="more-information-1">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/514">JEP 514</a>.</p>

<h4 id="jep-515-ahead-of-time-method-profiling">JEP 515: Ahead-of-Time Method Profiling</h4>

<p>The total set of classes that must be loaded for a Java application to run can’t be predicted by the application’s author before starting it.
For example, new classes can be loaded in response to external input.
So to truly know what a Java application does, we must run it.
This observation is supported by <a href="https://en.wikipedia.org/wiki/Rice's_theorem">Rice’s theorem</a>, which states that “static analysis can always be defeated by program complexity”.</p>

<p>While running an application, the JVM can identify which methods do the important work, and how they do it. 
For an application to reach peak performance, the JVM’s just-in-time compiler must find the unpredictable set of ‘hot’ methods, i.e., those which consume the most CPU time, and compile their bytecode to native code.</p>

<blockquote>
  <p>Fun fact: this is actually how the “HotSpot JVM” got its name!</p>
</blockquote>

<p>The HotSpot JVM has automatically collected this set of methods in the form of <em>profiles</em> since JDK 1.2.
Unfortunately, there is a chicken-and-egg problem: an application cannot achieve peak performance until its method behaviors are predicted, and method behaviors cannot be predicted until the application has run for a significant period of time.
This problem is currently solved by dedicating some resources to collecting profiles in the early part of an application’s run. 
During this ‘warmup period’ the application runs more slowly, until the JIT can compile the hot methods to native code.
After warmup, no more methods need to be compiled unless the application changes its pattern of behavior, triggering a new warmup period.</p>

<p>JEP 515 proposes to improve warmup time by collecting profiles even earlier, in a training run of the application, allowing the application to rapidly achieve peak performance.
To achieve this the AOT cache is extended to collect method profiles during training runs, that would otherwise be collected in the early part of an application’s run.
Accordingly, production runs of the application are both faster to start and faster to achieve peak performance.</p>

<p>Note that profiles cached during training runs do not prevent additional profiling during production runs, since an application’s behavior in production can diverge from what was observed in training. 
Even with cached profiles, the HotSpot JVM continues to profile and optimize the application as it runs, fusing the benefits of AOT profiles, on-line profiling, and JIT compilation.
The net effect of cached profiles is that the JIT runs earlier and with more accuracy, using the profiles to optimize the hot methods so that the application experiences a shorter warmup period. 
JIT tasks are inherently parallel, so the wall-clock time for warmup can be short when enough hardware resources are available.</p>

<p>To illustrate this, let’s look at a short program that uses the Stream API and thus causes almost 900 JDK classes to loaded. 
About 30 hot methods are compiled at the highest optimization level:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">java.util.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.stream.*</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloStreamWarmup</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="nc">String</span> <span class="nf">greeting</span><span class="o">(</span><span class="kt">int</span> <span class="n">n</span><span class="o">)</span> <span class="o">{</span>
        <span class="kt">var</span> <span class="n">words</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"Hello"</span><span class="o">,</span> <span class="s">""</span> <span class="o">+</span> <span class="n">n</span><span class="o">,</span> <span class="s">"world!"</span><span class="o">);</span>
        <span class="k">return</span> <span class="n">words</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
            <span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">w</span> <span class="o">-&gt;</span> <span class="o">!</span><span class="n">w</span><span class="o">.</span><span class="na">contains</span><span class="o">(</span><span class="s">"0"</span><span class="o">))</span>
            <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">joining</span><span class="o">(</span><span class="s">", "</span><span class="o">));</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">...</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">100_000</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span>
            <span class="n">greeting</span><span class="o">(</span><span class="n">i</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">greeting</span><span class="o">(</span><span class="mi">0</span><span class="o">));</span>  <span class="c1">// "Hello, world!"</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This program runs in 90 milliseconds  with an AOT cache that contains no profiles. 
After collecting profiles into the AOT cache, it runs in 73 milliseconds — an improvement of 19%. 
The AOT cache with profiles occupies an additional 250 kilobytes, about 2.5% more than the AOT cache without profiles.</p>

<p>A short program such as this has only a short warmup period, but with cached profiles that warmup goes even faster as a result of timely and accurate JIT activity. 
More complex and longer-running programs are also likely to warm up more quickly, for the same reason.</p>

<h5 id="more-information-2">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/515">JEP 515</a>.</p>

<h3 id="security-libs">Security Libs</h3>

<p>Java 25 introduces a single new feature that is part of the Security Libs:</p>

<ul>
  <li>PEM Encodings of Cryptographic Objects (Preview)</li>
</ul>

<h4 id="jep-470-pem-encodings-of-cryptographic-objects-preview">JEP 470: PEM Encodings of Cryptographic Objects (Preview)</h4>

<p>Within a Java context, cryptographic objects such as public keys, private keys and certificates can be easily created and distributed. But outside of the Java world, the de facto standard is the <a href="https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail">Privacy-Enhanced Mail</a> (PEM) format. Let’s see an example of a PEM-encoded cryptographic object:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEi/kRGOL7wCPTN4KJ2ppeSt5UYB6u
cPjjuKDtFTXbguOIFDdZ65O/8HTUqS/sVzRF+dg7H3/tkQ/36KdtuADbwQ==
-----END PUBLIC KEY-----
</code></pre></div></div>

<p>The Java Platform currently doesn’t include an easy-to-use API for decoding and encoding text in the PEM format, which means that decoding a PEM-encoded key can be a tedious job that involves careful parsing of the source PEM text. To further illustrate this point, encrypting and decrypting a private key currently requires over a dozen lines of code.</p>

<p>To solve this problem, JEP 470 introduces an API that can encode objects to the PEM format. It effectively acts as a bridge between Base64 and cryptographic objects. It involves a new interface and three new classes, in the <code class="language-plaintext highlighter-rouge">java.security</code> package:</p>

<dl>
  <dt><a href="https://cr.openjdk.org/~ascarpino/pem/api/java.base/java/security/DEREncodable.html"><code class="language-plaintext highlighter-rouge">DEREncodable</code></a></dt>
  <dd>A sealed interface that groups together all cryptographic objects that support converting their instances to and from byte arrays in the <a href="https://en.wikipedia.org/wiki/X.690#DER_encoding">Distinguished Encoding Rules</a> (DER) format.</dd>
  <dt><a href="https://cr.openjdk.org/~ascarpino/pem/api/java.base/java/security/PEMEncoder.html"><code class="language-plaintext highlighter-rouge">PEMEncoder</code></a></dt>
  <dd>A class that declares methods for encoding <code class="language-plaintext highlighter-rouge">DEREncodable</code> objects into PEM text.</dd>
  <dt><a href="https://cr.openjdk.org/~ascarpino/pem/api/java.base/java/security/PEMDecoder.html"><code class="language-plaintext highlighter-rouge">PEMDecoder</code></a></dt>
  <dd>A class that declares methods for decoding PEM text to <code class="language-plaintext highlighter-rouge">DEREncodable</code> objects.</dd>
  <dt><a href="https://cr.openjdk.org/~ascarpino/pem/api/java.base/java/security/PEMRecord.html"><code class="language-plaintext highlighter-rouge">PEMRecord</code></a></dt>
  <dd>A record that implements <code class="language-plaintext highlighter-rouge">DEREncodable</code>, which can hold any type of PEM data. It allows you to encode and decode PEM tests yielding cryptographic objects for which no Java representation currently exists.</dd>
</dl>

<h5 id="typical-usage">Typical Usage</h5>

<p>The following code example shows typical usage of the API:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">PrivateKey</span> <span class="n">privateKey</span> <span class="o">=</span> <span class="o">...;</span>
<span class="nc">PublicKey</span> <span class="n">publicKey</span> <span class="o">=</span> <span class="o">...;</span>

<span class="c1">// let's encode a cryptographic object!</span>
<span class="nc">PEMEncoder</span> <span class="n">pemEncoder</span> <span class="o">=</span> <span class="nc">PEMEncoder</span><span class="o">.</span><span class="na">of</span><span class="o">();</span>

<span class="c1">// this returns PEM text in a byte array</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">privateKeyPem</span> <span class="o">=</span> <span class="n">pemEncoder</span><span class="o">.</span><span class="na">encode</span><span class="o">(</span><span class="n">privateKey</span><span class="o">);</span>

<span class="c1">// this returns PEM text in a String</span>
<span class="nc">String</span> <span class="n">keyPairPem</span> <span class="o">=</span> <span class="n">pemEncoder</span><span class="o">.</span><span class="na">encodeToString</span><span class="o">(</span><span class="k">new</span> <span class="nc">KeyPair</span><span class="o">(</span><span class="n">privateKey</span><span class="o">,</span> <span class="n">publicKey</span><span class="o">));</span> 

<span class="c1">// this returns encrypted PEM text</span>
<span class="nc">String</span> <span class="n">password</span> <span class="o">=</span> <span class="s">"java-first-java-always"</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">pem</span> <span class="o">=</span> <span class="n">pemEncoder</span><span class="o">.</span><span class="na">withEncryption</span><span class="o">(</span><span class="n">password</span><span class="o">).</span><span class="na">encodeToString</span><span class="o">(</span><span class="n">privateKey</span><span class="o">);</span>

<span class="c1">// let's decode a cryptographic object!</span>
<span class="nc">PEMDecoder</span> <span class="n">pemDecoder</span> <span class="o">=</span> <span class="nc">PEMDecoder</span><span class="o">.</span><span class="na">of</span><span class="o">();</span>

<span class="c1">// this returns a DEREncodable, so we need to pattern-match</span>
<span class="k">switch</span> <span class="o">(</span><span class="n">pemDecoder</span><span class="o">.</span><span class="na">decode</span><span class="o">(</span><span class="n">pem</span><span class="o">))</span> <span class="o">{</span>
    <span class="k">case</span> <span class="nc">PublicKey</span> <span class="n">publicKey</span> <span class="o">-&gt;</span> <span class="o">...;</span>
    <span class="k">case</span> <span class="nc">PrivateKey</span> <span class="n">privateKey</span> <span class="o">-&gt;</span> <span class="o">...;</span>
    <span class="k">default</span> <span class="o">-&gt;</span> <span class="k">throw</span> <span class="k">new</span> <span class="nc">IllegalArgumentException</span><span class="o">(</span><span class="s">"Unsupported cryptographic object"</span><span class="o">);</span>
<span class="o">}</span>

<span class="c1">// alternatively, if you know the type of the encoded cryptographic object in advance:</span>
<span class="nc">PrivateKey</span> <span class="n">key</span> <span class="o">=</span> <span class="n">pemDecoder</span><span class="o">.</span><span class="na">decode</span><span class="o">(</span><span class="n">pem</span><span class="o">,</span> <span class="nc">PrivateKey</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>

<span class="c1">// this decodes an encrypted cryptographic object</span>
<span class="nc">PrivateKey</span> <span class="n">decryptedkey</span> <span class="o">=</span> <span class="n">pemDecoder</span><span class="o">.</span><span class="na">withDecryption</span><span class="o">(</span><span class="n">password</span><span class="o">).</span><span class="na">decode</span><span class="o">(</span><span class="n">pem</span><span class="o">,</span> <span class="nc">PrivateKey</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
</code></pre></div></div>

<h5 id="preview-warning-1">Preview Warning</h5>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h5 id="more-information-3">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/470">JEP 470</a>.</p>

<h3 id="java-flight-recorder">Java Flight Recorder</h3>

<p>Java 25 introduces three new features that are part of the Java Flight Recorder:</p>

<ul>
  <li>JFR CPU-Time Profiling (Experimental)</li>
  <li>JFR Cooperative Sampling</li>
  <li>JFR Method Timing &amp; Tracing</li>
</ul>

<blockquote>
  <p>The Java Flight Recorder is an event recorder built into the JVM. It captures information about the JVM itself – and the applications running in it – not unlike a data flight recorder (or ‘black box’) in a commercial aircraft.</p>
</blockquote>

<h4 id="jep-509-jfr-cpu-time-profiling-experimental">JEP 509: JFR CPU-Time Profiling (Experimental)</h4>

<p><em>Profiling</em> is the act of measuring the consumption of computational resources such as memory, CPU cycles and elapsed time.
The resulting measurements can help make a program more efficient, by identifying which program elements to optimize.
One would typically prioritize optimizing those elements that consume the most resources.</p>

<p>The Java Flight Recorder (or JFR) is the JDK’s profiling and monitoring facility, commonly used to profile heap memory and CPU usage.
Its support of heap allocation profiling is good, but its implementation of CPU profiling currently comes with a few drawbacks:</p>

<ul>
  <li>it’s only able to approximate CPU-cycle consumption by emitting a sample of running Java threads (in the form of a stacktrace) in a JFR event at regular time intervals (say, every 20 ms);</li>
  <li>it doesn’t include threads that are running native code;</li>
  <li>obtaining the sample may fail without reporting it;</li>
  <li>the sample contains a subset of running threads only.</li>
</ul>

<p>This means that the resulting profile may be inaccurate and not reflect the actual CPU usage profile, and this effect is amplified when sample collecting occurs over a relatively short period of time.</p>

<h5 id="towards-more-accurate-measurements">Towards More Accurate Measurements</h5>

<p>Version 2.6.12 of the Linux kernel added the ability to accurately measure CPU-cycle consumption through a timer that emits signals at fixed intervals of elapsed <em>CPU time</em> (rather than real time).
JEP 509 enhances the JFR to make use of this timer, producing more accurate CPU-time profiles than could be obtained through the current sampling approach.
On top of that, also CPU cycles that are consumed by Java applications running native code would be correctly tracked.</p>

<h5 id="usage">Usage</h5>

<p>JFR will use Linux’s CPU-timer mechanism to sample the stack of <em>every</em> thread running Java code at fixed intervals of elapsed CPU time. 
Each such sample is recorded in a new type of event, called <code class="language-plaintext highlighter-rouge">jdk.CPUTimeSample</code>. 
This event is not enabled by default.</p>

<p>Here’s how to enable the event when running the JFR:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:StartFlightRecording<span class="o">=</span>jdk.CPUTimeSample#enabled<span class="o">=</span><span class="nb">true</span>,filename<span class="o">=</span>profile.jfr ...
</code></pre></div></div>

<p>Note that his feature will currently only be available on Linux systems.
CPU-time profiling may be added to the JFR on other platforms in the future.</p>

<h5 id="more-information-4">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/509">JEP 509</a>. It contains a few more details on how to use the new JFR event and what a typical flame graph would look like.</p>

<h4 id="jep-518-jfr-cooperative-sampling">JEP 518: JFR Cooperative Sampling</h4>

<p>We learned in the previous section that the JFR collects samples by obtaining stacktraces for a number of running Java threads.
In order to produce these stacktraces, the target threads must be suspended so that the call frames on the stack can be parsed.
As part of that process, the Hotspot JVM maintains metadata that is valid only when the thread is suspended at well-defined code locations known as <em>safepoints</em>.
However, if sampling is only done at safepoints, the notorious <a href="https://plv.colorado.edu/papers/mytkowicz-pldi10.pdf">safety bias problem</a> occurs — where accuracy is lost since frequently-executed pieces of code might not be anywhere near a safepoint.</p>

<p>To avoid this problem, the JFR currently samples the stacks of program threads asynchronously, suspending threads at code locations that may not be safepoints at all. 
This means the metadata maintained by the JVM may not be valid and so we have to resort to using heuristics to generate a stacktrace.
Unfortunately, these heuristics are inefficient, and may even crash the JVM when their results are incorrect.</p>

<p>JEP 518 proposes to avoid the need for these heuristics by parsing thread stacks only at safepoints.
It comes with a different approach to avoid the safepoint bias problem: taking samples cooperatively.
When it is time to take a sample, JFR’s sampler thread still suspends the target thread. 
But rather than attempting to parse the stack, it just records the target’s program counter and stack pointer in a sample request, which it appends to an internal thread-local queue. 
It then arranges for the target thread to stop at its next safepoint, and resumes the thread.</p>

<p>The target thread now runs normally until its next safepoint. At that time, the safepoint handling code inspects the queue. 
If it finds any sample requests, then, for each one, it reconstructs a stack trace, adjusting for safepoint bias, and emits a JFR execution-time sampling event.</p>

<h5 id="more-information-5">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/518">JEP 518</a>.</p>

<h4 id="jep-520-jfr-method-timing--tracing">JEP 520: JFR Method Timing &amp; Tracing</h4>

<p>When performance-related problems arise, knowing how much time is spent in which code unit can be very valuable.
You may have just introduced a method that takes particularly long to execute.
Or a static initializer may cause your application to take an unusually long time to start.
In such cases, during development, execution of these code units can be analyzed by using debuggers or the <a href="https://github.com/openjdk/jmh">Java Microbenchmark Harness</a>.</p>

<p>However, during testing and production, far less feasible options exist.
Sample-based profilers can capture stack traces for frequently executed methods, but can’t provide timing and tracing for all invocations.
And the <a href="https://www.oracle.com/java/technologies/jdk-mission-control.html">JDK Mission Control tool</a> can certainly instrument methods to emit JFR events, but not without significant performance overhead.</p>

<p>JEP 520 introduces two new JFR events (<code class="language-plaintext highlighter-rouge">jdk.MethodTiming</code> and <code class="language-plaintext highlighter-rouge">jdk.MethodTrace</code>) that both accept a filter to select the methods to time and trace.</p>

<p>For example, to see what triggers the resize of a <code class="language-plaintext highlighter-rouge">HashMap</code>, you can configure the <code class="language-plaintext highlighter-rouge">MethodTrace</code> event’s filter when making a recording and then use the <a href="https://docs.oracle.com/en/java/javase/24/docs/specs/man/jfr.html"><code class="language-plaintext highlighter-rouge">jfr</code></a> tool to display the recorded event:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:StartFlightRecording:jdk.MethodTrace#filter<span class="o">=</span>java.util.HashMap::resize,filename<span class="o">=</span>recording.jfr ...
<span class="nv">$ </span>jfr print <span class="nt">--events</span> jdk.MethodTrace <span class="nt">--stack-depth</span> 20 recording.jfr
jdk.MethodTrace <span class="o">{</span>
    startTime <span class="o">=</span> 00:39:26.379 <span class="o">(</span>2025-03-05<span class="o">)</span>
    duration <span class="o">=</span> 0.00113 ms
    method <span class="o">=</span> java.util.HashMap.resize<span class="o">()</span>
    eventThread <span class="o">=</span> <span class="s2">"main"</span> <span class="o">(</span>javaThreadId <span class="o">=</span> 3<span class="o">)</span>
    stackTrace <span class="o">=</span> <span class="o">[</span>
      java.util.HashMap.putVal<span class="o">(</span>int, Object, Object, boolean, boolean<span class="o">)</span> line: 636
      java.util.HashMap.put<span class="o">(</span>Object, Object<span class="o">)</span> line: 619
      sun.awt.AppContext.put<span class="o">(</span>Object, Object<span class="o">)</span> line: 598
      sun.awt.AppContext.&lt;init&gt;<span class="o">(</span>ThreadGroup<span class="o">)</span> line: 240
      sun.awt.SunToolkit.createNewAppContext<span class="o">(</span>ThreadGroup<span class="o">)</span> line: 282
      sun.awt.AppContext.initMainAppContext<span class="o">()</span> line: 260
      sun.awt.AppContext.getAppContext<span class="o">()</span> line: 295
      sun.awt.SunToolkit.getSystemEventQueueImplPP<span class="o">()</span> line: 1024
      sun.awt.SunToolkit.getSystemEventQueueImpl<span class="o">()</span> line: 1019
      java.awt.Toolkit.getEventQueue<span class="o">()</span> line: 1375
      java.awt.EventQueue.invokeLater<span class="o">(</span>Runnable<span class="o">)</span> line: 1257
      javax.swing.SwingUtilities.invokeLater<span class="o">(</span>Runnable<span class="o">)</span> line: 1415
      java2d.J2Ddemo.main<span class="o">(</span>String[]<span class="o">)</span> line: 674
    <span class="o">]</span>
<span class="o">}</span>
</code></pre></div></div>

<p>As you can see, the filter is specified just like a <a href="https://docs.oracle.com/javase/specs/jls/se24/html/jls-15.html#jls-15.13">method reference</a>.
As the JVM starts up, it instruments the targeted method by injecting bytecode to emit a <code class="language-plaintext highlighter-rouge">MethodTrace</code> event.</p>

<h5 id="configuration-files">Configuration Files</h5>

<p>The JFR is usually configured via a configuration file, which has now also been enhanced to support method timing and tracing. Additionally, the <code class="language-plaintext highlighter-rouge">jfr view</code> and <code class="language-plaintext highlighter-rouge">jcmd &lt;pid&gt; JFR.view</code> commands have been enhanced to display method timing and tracing results.</p>

<p>To put this all together, if an application suffers from slow startup, timing the execution of all static initializers may suggest where lazy initialization could be used. We can time all static initializers in all classes by omitting the class name, specifying <code class="language-plaintext highlighter-rouge">::&lt;clinit&gt;</code> as the filter:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="s1">'-XX:StartFlightRecording:method-timing=::&lt;clinit&gt;,filename=clinit.jfr'</span> ...
<span class="nv">$ </span>jfr view method-timing clinit.jfr

                                 Method Timing

Timed Method                                           Invocations Average Time
<span class="nt">------------------------------------------------------</span> <span class="nt">-----------</span> <span class="nt">------------</span>
sun.font.HBShaper.&lt;clinit&gt;<span class="o">()</span>                                     1 32.500000 ms
java.awt.GraphicsEnvironment<span class="nv">$LocalGE</span>.&lt;clinit&gt;<span class="o">()</span>                  1 32.400000 ms
java2d.DemoFonts.&lt;clinit&gt;<span class="o">()</span>                                      1 21.200000 ms
java.nio.file.TempFileHelper.&lt;clinit&gt;<span class="o">()</span>                          1 17.100000 ms
sun.security.util.SecurityProviderConstants.&lt;clinit&gt;<span class="o">()</span>           1  9.860000 ms
java.awt.Component.&lt;clinit&gt;<span class="o">()</span>                                    1  9.120000 ms
sun.font.SunFontManager.&lt;clinit&gt;<span class="o">()</span>                               1  8.350000 ms
sun.java2d.SurfaceData.&lt;clinit&gt;<span class="o">()</span>                                1  8.300000 ms
java.security.Security.&lt;clinit&gt;<span class="o">()</span>                                1  8.020000 ms
sun.security.util.KnownOIDs.&lt;clinit&gt;<span class="o">()</span>                           1  7.550000 ms
...
</code></pre></div></div>

<h5 id="filtering-on-classes-and-annotations">Filtering on Classes and Annotations</h5>

<p>To time or trace multiple methods, a filter can mention a class or an annotation.
For example, to see the number of times that a Jakarta REST endpoint is invoked, and measure the approximate execution time:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>jcmd &lt;pid&gt; JFR.start method-timing<span class="o">=</span>@jakarta.ws.rs.GET
</code></pre></div></div>

<p>Multiple filters can be specified, separated by semicolons.</p>

<h5 id="benefits">Benefits</h5>

<p>This new approach comes with both performance and usability benefits. As we have seen, the JVM can filter methods, eliminating the need to parse the bytecode of every loaded class twice. And because can methods be timed and traced without having to configure or install an agent, usability improves as well.</p>

<h5 id="more-information-6">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/520">JEP 520</a>.</p>

<h2 id="repreviews-and-finalizations">Repreviews and Finalizations</h2>

<p>Now it’s time to take a look at a few features that may already be familiar to you, because they were introduced in a previous version of Java. They have been repreviewed (or finalized) in Java 25, with only minor changes compared to Java 24 in most cases. Therefore, to avoid a very lengthy article, we’ll outline these changes and link to a previous article for a full feature description, should you wish to refresh your memory.</p>

<h3 id="jep-505-structured-concurrency-fifth-preview">JEP 505: Structured Concurrency (Fifth Preview)</h3>

<p><em>Structured concurrency</em> treats groups of related tasks running in different threads as a single unit of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability.</p>

<h4 id="whats-different-from-java-24">What’s Different From Java 24?</h4>

<p>In Java 25, a <code class="language-plaintext highlighter-rouge">StructuredTaskScope</code> can be opened via static factory methods rather than through public constructors. The zero-parameter <code class="language-plaintext highlighter-rouge">open()</code> factory method covers the common case by creating a <code class="language-plaintext highlighter-rouge">StructuredTaskScope</code> that waits for all subtasks to succeed or any subtask to fail. Other policies and outcomes can be implemented by providing an appropriate <a href="https://download.java.net/java/early_access/jdk25/docs/api/java.base/java/util/concurrent/StructuredTaskScope.Joiner.html"><code class="language-plaintext highlighter-rouge">Joiner</code></a> to one of the richer <code class="language-plaintext highlighter-rouge">open(Joiner)</code> factory methods.</p>

<h4 id="preview-warning-2">Preview Warning</h4>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-7">More Information</h4>

<p>If you prefer to get more information on the current state of this feature, then read <a href="https://openjdk.org/jeps/505">JEP 505</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-480-structured-concurrency-third-preview">full feature description</a> from a previous article.</p>

<h3 id="jep-506-scoped-values">JEP 506: Scoped Values</h3>

<p><em>Scoped values</em> enable the sharing of immutable data within and across threads. 
They are preferred to thread-local variables, especially when using a large number of (virtual) threads.</p>

<h4 id="whats-different-from-java-24-1">What’s Different From Java 24?</h4>

<p>A single change was made to the API compared to Java 24:</p>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">ScopedValue.orElse()</code> method no longer accepts <code class="language-plaintext highlighter-rouge">null</code> as its argument.</li>
</ul>

<p>On top of that, the preview status has been dropped, which means the scoped values API is now finalized!</p>

<h4 id="more-information-8">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/506">JEP 506</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-481-scoped-values-third-preview">full feature description</a> from a previous article.</p>

<h3 id="jep-507-primitive-types-in-patterns-instanceof-and-switch-third-preview">JEP 507: Primitive Types in Patterns, instanceof, and switch (Third Preview)</h3>

<p>Pattern matching now supports primitive types in all pattern contexts. On top of that, the <code class="language-plaintext highlighter-rouge">instanceof</code> and <code class="language-plaintext highlighter-rouge">switch</code> constructs have been extended to also work with all primitive types.</p>

<h4 id="whats-different-from-java-24-2">What’s Different From Java 24?</h4>

<p>Compared to the preview version of this feature in Java 24, nothing was changed or added. JEP 507 simply exists to gather more feedback from users.</p>

<h4 id="preview-warning-3">Preview Warning</h4>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-9">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/507">JEP 507</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-455-primitive-types-in-patterns-instanceof-and-switch-preview">full feature description</a> from a previous article.</p>

<h3 id="jep-508-vector-api-tenth-incubator">JEP 508: Vector API (Tenth Incubator)</h3>

<p>The Vector API makes it possible to express vector computations that reliably compile at runtime to optimal vector instructions. 
This means that these computations will significantly outperform equivalent scalar computations on the supported CPU architectures (x64 and AArch64).</p>

<h4 id="whats-different-from-java-24-3">What’s Different From Java 24?</h4>

<p>The following changes were made to the Vector API compared to Java 23:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">VectorShuffle</code> now supports access to and from <code class="language-plaintext highlighter-rouge">MemorySegment</code>;</li>
  <li>The implementation now links to native mathematical-function libraries via the Foreign Function &amp; Memory API (<a href="https://openjdk.org/jeps/454">JEP 454</a>) rather than custom C++ code inside the HotSpot JVM, thereby improving maintainability;</li>
  <li>Addition, subtraction, division, multiplication, square root, and fused multiply/add operations on <code class="language-plaintext highlighter-rouge">Float16</code> values are now auto-vectorized on supporting x64 CPUs.</li>
</ul>

<p>The Vector API will keep incubating until necessary features of Project Valhalla become available as preview features. When that happens, the Vector API will be adapted to use them, and it will be promoted from incubation to preview.</p>

<h4 id="more-information-10">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/508">JEP 508</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-469-vector-api-eighth-incubator">full feature description</a> from a previous article.</p>

<h3 id="jep-510-key-derivation-function-api">JEP 510: Key Derivation Function API</h3>

<p>To be able to withstand practical quantum computing attacks, it is Java’s long-term goal is to eventually implement Hybrid Public Key Encryption (HPKE), which facilitates a seamless transition to quantum-resistant encryption methods. To that end, Java 24 introduced a new Key Derivation Function API, which is now finalized in Java 25.</p>

<p><em>Key derivation functions</em> are cryptographic algorithms for deriving additional keys from a secret key and other data. A KDF allows keys to be created in a manner that is both secure and reproducible by two parties sharing knowledge of the inputs. Deriving keys is similar to hashing passwords. A KDF employs a keyed hash along with extra entropy from its other inputs to either derive new key material or safely expand existing values into a larger quantity of key material.</p>

<h4 id="whats-different-from-java-24-4">What’s Different From Java 24?</h4>

<p>Compared to the preview version of this feature in Java 24, the preview status has been dropped, which means the Key Derivation Function API is now finalized!</p>

<h4 id="more-information-11">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/510">JEP 510</a> or the <a href="https://hanno.codes/2025/03/18/java-24-rolls-out-today/#jep-478-key-derivation-function-api-preview">full feature description</a> from a previous article.</p>

<h3 id="jep-511-module-import-declarations">JEP 511: Module Import Declarations</h3>

<p>Module import declarations import all of the public top-level classes and interfaces in the packages exported by that module. They are a shorter alternative for listing many imports that originate from the same root package.</p>

<h4 id="whats-different-from-java-24-5">What’s Different From Java 24?</h4>

<p>This feature was in second preview in Java 24, and in Java 25 the preview status has been dropped. This means module import declarations are now finalized!</p>

<h4 id="more-information-12">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/511">JEP 511</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-476-module-import-declarations-preview">full feature description</a> from a previous article.</p>

<h3 id="jep-512-compact-source-files-and-instance-main-methods">JEP 512: Compact Source Files and Instance Main Methods</h3>

<p>Comapct source files allow developers to write Java programs without the need to explicitly declare a class. They can contain ‘instance main methods’: a shorter form of the classic <code class="language-plaintext highlighter-rouge">main()</code> method without requiring program arguments or imports. These two features simplify the process of writing small programs and scripts by reducing boilerplate code.</p>

<h4 id="whats-different-from-java-24-6">What’s Different From Java 24?</h4>

<p>The feature that used to be known as ‘simple source files’ was renamed to ‘compact source files’.
On top of that, several minor improvements are now in place based on developer feedback:</p>

<ul>
  <li>The new <code class="language-plaintext highlighter-rouge">IO</code> class for basic console I/O is now in the <code class="language-plaintext highlighter-rouge">java.lang</code> package rather than the <code class="language-plaintext highlighter-rouge">java.io</code> package. Thus it is implicitly imported by every source file.</li>
  <li>The implementation of the <code class="language-plaintext highlighter-rouge">IO</code> class is now based upon <code class="language-plaintext highlighter-rouge">System.out</code> and <code class="language-plaintext highlighter-rouge">System.in</code> rather than the <code class="language-plaintext highlighter-rouge">java.io.Console</code> class.</li>
  <li>The static methods of the <code class="language-plaintext highlighter-rouge">IO</code> class are no longer implicitly imported into compact source files. Thus invocations of these methods must name the class, e.g., <code class="language-plaintext highlighter-rouge">IO.println("Hello, world!")</code>, unless the methods are explicitly imported.</li>
</ul>

<p>This last change has been made to make a beginner’s first experience with Java a bit easier. When the static methods of the <code class="language-plaintext highlighter-rouge">IO</code> class were automatically imported, this had the pleasing effect of making the methods in <code class="language-plaintext highlighter-rouge">IO</code> appear to be built-in to the Java language. However, to evolve a compact source file into an ordinary source file, a beginner would have to add a static import declaration - an advanced concept that a beginner should definitely not tackle on their first day.</p>

<h4 id="more-information-13">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/512">JEP 512</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-477-implicitly-declared-classes-and-instance-main-methods-third-preview">full feature description</a> from a previous article.</p>

<h3 id="jep-513-flexible-constructor-bodies">JEP 513: Flexible Constructor Bodies</h3>

<p>Flexible constructor bodies allow statements to appear before an explicit constructor invocation, like <code class="language-plaintext highlighter-rouge">super(..)</code> or <code class="language-plaintext highlighter-rouge">this(..)</code>. The statements cannot reference the instance under construction, but they can initialize its fields. Initializing fields before invoking another constructor makes a class more reliable when methods are overridden.</p>

<h4 id="whats-different-from-java-24-7">What’s Different From Java 24?</h4>

<p>Compared to the preview version of this feature in Java 24, the preview status has been dropped, which means flexible constructor bodies are now finalized!</p>

<h4 id="more-information-14">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/513">JEP 513</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-482-flexible-constructor-bodies-second-preview">full feature description</a>) from a previous article.</p>

<h3 id="jep-519-compact-object-headers">JEP 519: Compact Object Headers</h3>

<p>JDK 24 introduced compact object headers as an experimental feature, which enabled a reduction of the object header size to 64 bits. Since then, compact object headers have proven their stability and performance. They have been tested at Oracle by running the full JDK test suite. They have also been tested at Amazon by hundreds of services in production, most of them using backports of the feature to JDK 21 and JDK 17. On top of that, various other experiments have demonstrated that enabling compact object headers improves performance.</p>

<h4 id="whats-different-from-java-24-8">What’s Different From Java 24?</h4>

<p>The experimental status has been dropped, which means compact object headers have now become a product feature. They can be enabled via the command-line options:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:+UseCompactObjectHeaders ...
</code></pre></div></div>

<p>This means the <code class="language-plaintext highlighter-rouge">-XX:+UnlockExperimentalVMOptions</code> option that was required in Java 24 is no longer necessary. In later releases, we can expect the feature to become enabled by default. Eventually the code for legacy object headers will be removed altogether.</p>

<h4 id="more-information-15">More Information</h4>

<p>For more information on this feature, including references to the conducted experiments that proved the better performance, read <a href="https://openjdk.org/jeps/519">JEP 519</a> or the <a href="https://hanno.codes/2025/03/18/java-24-rolls-out-today/#jep-450-compact-object-headers-experimental">full feature description</a> from a previous article.</p>

<h3 id="jep-521-generational-shenandoah">JEP 521: Generational Shenandoah</h3>

<p>The Shenandoah garbage collector is an ultra-low pause time garbage collector. It has been <a href="https://openjdk.org/jeps/379">available for production use since Java 15</a> and has been designed to dramatically reduce garbage collection pause times, regardless of the heap size that is used. It can achieve these low pause times because most of the work is done before the GC pause, in a series of preparation steps. Shenandoah marks and compacts any heap objects eligible for garbage collection, while regular Java user threads are still running.</p>

<p>Java 24 introduced an experimental extension to Shenandoah that maintains separate generations for young and old objects, allowing Shenandoah to collect young objects more frequently. This results in a significant performance gain for applications running with generational Shenandoah, without sacrificing any of the valuable properties that the garbage collector is already known for.</p>

<p>The reason for handling young and old objects separately stems from the <a href="https://docs.oracle.com/en/java/javase/17/gctuning/garbage-collector-implementation.html#GUID-71D796B3-CBAB-4D80-B5C3-2620E45F6E5D">weak generational hypothesis</a>, which states that young objects tend to die young, while old objects tend to stick around. This means that collecting young objects requires fewer resources and yields more memory, while collecting old objects requires more resources and yields less memory. This is the reason we can improve the performance of applications that use Shenandoah by collecting young objects more frequently.</p>

<h4 id="whats-different-from-java-24-9">What’s Different From Java 24?</h4>

<p>The experimental status has now been dropped, which means generational mode has now become a product feature. Compared to JDK 24, many stability and performance improvements have been implemented, and extensive testing on multiple platforms has been performed.</p>

<p>To run your workload with generational Shenandoah in Java 25, the following configuration is needed:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java ... <span class="nt">-XX</span>:+UseShenandoahGC <span class="nt">-XX</span>:ShenandoahGCMode<span class="o">=</span>generational
</code></pre></div></div>

<p>This means the <code class="language-plaintext highlighter-rouge">-XX:+UnlockExperimentalVMOptions</code> option that was required in Java 24 is no longer necessary. Note that no changes were made to Shenandoah’s default behaviour. This may still change in a future release, though.</p>

<h4 id="more-information-16">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/521">JEP 521</a> or the <a href="https://hanno.codes/2025/03/18/java-24-rolls-out-today/#jep-404-generational-shenandoah-experimental">full feature description</a> from a previous article.</p>

<h2 id="deprecations-removals--restrictions">Deprecations, Removals &amp; Restrictions</h2>

<p>Java 25 comes with a single removal.</p>

<h3 id="jep-503-remove-the-32-bit-x86-port">JEP 503: Remove the 32-bit x86 Port</h3>

<p>This JEP removes the 32-bit x86 (Linux) port, which was to be expected after <a href="https://hanno.codes/2025/03/18/java-24-rolls-out-today/#jep-501-deprecate-the-32-bit-x86-port-for-removal">its deprecation in Java 24</a>. The affected users are expected to already have migrated to 64-bit JVMs.</p>

<p>Supporting multiple platforms has been the focus of the Java ecosystem since the beginning. But older platforms cannot be supported indefinitely—the effort that was required to maintain this port exceeded its advantages. Keeping it up-to-date with new features like Loom, the Foreign Function &amp; Memory API (FFM), the Vector API, and late GC barrier expansion represented a significant cost. So it’s time to say goodbye to this port!</p>

<h4 id="more-information-17">More Information</h4>

<p>For more information on this removal, read <a href="https://openjdk.org/jeps/503">JEP 503</a>.</p>

<h2 id="final-thoughts">Final thoughts</h2>

<p>And that concludes our discussion of the 18 JEP’s that come with Java 25. 
But that’s not even all that’s new: <a href="https://jdk.java.net/25/release-notes">many other updates</a> were included in this release, including various performance, stability and security updates. 
One thing is for sure: this version of Java is ready to perform to the limit.
So what are you waiting for? 
It’s time to take this brand-new Java release for a high-performance spin!</p>]]></content><author><name>Hanno Embregts</name></author><category term="java" /><summary type="html"><![CDATA[Here's Java 25, ready to perform to the limit. It introduces stable values, and intensifies its focus on performance as more JEPs emerge from Project Leyden. On top of that, the Java Flight Recorder is now more equipped than ever to tackle performance issues. This post has all the info!]]></summary></entry><entry><title type="html">Java 24 Rolls Out Today! Find Out Why It’s Aptly Named</title><link href="https://hanno.codes/2025/03/18/java-24-rolls-out-today/" rel="alternate" type="text/html" title="Java 24 Rolls Out Today! Find Out Why It’s Aptly Named" /><published>2025-03-18T02:30:00+00:00</published><updated>2025-03-18T02:30:00+00:00</updated><id>https://hanno.codes/2025/03/18/java-24-rolls-out-today</id><content type="html" xml:base="https://hanno.codes/2025/03/18/java-24-rolls-out-today/"><![CDATA[<p>Java 24 rolls out today! It’s been six months since Java 23 was released, so it’s time for another helping of new features. And this particular release of Java is aptly named, because it contains exactly 24 JEPs. Coincidence? I think not. 🙂</p>

<p>Java 24 brings a diverse set of features, delivering performance improvements like compact object headers, garbage collection optimizations and the first JEP to come out of Project Leyden. On top of that, various security features related to the quantum computing field were added, and a solution to virtual thread pinning is now available!</p>

<p>Apart from these, a few new features from older releases have been repreviewed.</p>

<blockquote>
  <p>Short descriptions of the repreviewed features are provided to prevent this article from becoming a bit too lengthy. Each repreviewed feature has a link to a longer description of the feature should you wish to learn more.</p>
</blockquote>

<p><img src="/assets/images/blog/basketball-24.jpg" alt="Basketball players hugging during game - one of them wears a jersey with number '24' at the back" /></p>
<blockquote>
  <p>Photo by Royy Nguyen, from <a href="https://www.pexels.com/photo/basketball-players-hugging-during-game-in-gym-5303477/">Pexels</a></p>
</blockquote>

<h2 id="jep-overview">JEP Overview</h2>

<p>To start off, let’s look at an overview of the JEPs that ship with Java 24. This table contains the preview status for all JEP’s, to which project they belong, what kind of features they add and the things that have changed since Java 23.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right"><strong>JEP</strong></th>
      <th><strong>Title</strong></th>
      <th style="text-align: right"><strong>Status</strong></th>
      <th style="text-align: right"><strong>Project</strong></th>
      <th style="text-align: right"><strong>Feature Type</strong></th>
      <th style="text-align: right"><strong>Changes since Java 23</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right"><strong>404</strong></td>
      <td>Generational Shenandoah</td>
      <td style="text-align: right">Experimental</td>
      <td style="text-align: right">HotSpot / GC</td>
      <td style="text-align: right">Performance</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>450</strong></td>
      <td>Compact Object Headers</td>
      <td style="text-align: right">Experimental</td>
      <td style="text-align: right">HotSpot</td>
      <td style="text-align: right">Performance</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>472</strong></td>
      <td>Prepare to Restrict the Use of JNI</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Core Libs</td>
      <td style="text-align: right">Deprecation</td>
      <td style="text-align: right">Deprecation</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>475</strong></td>
      <td>Late Barrier Expansion for G1</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">HotSpot / GC</td>
      <td style="text-align: right">Performance</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>478</strong></td>
      <td>Key Derivation Function API</td>
      <td style="text-align: right">Preview</td>
      <td style="text-align: right">Security Libs</td>
      <td style="text-align: right">Security</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>479</strong></td>
      <td>Remove the Windows 32-bit x86 Port</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">HotSpot</td>
      <td style="text-align: right">Deprecation</td>
      <td style="text-align: right">Deprecation</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>483</strong></td>
      <td>Ahead-of-Time Class Loading &amp; Linking</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">HotSpot</td>
      <td style="text-align: right">Performance</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>484</strong></td>
      <td>Class-File API</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Core Libs</td>
      <td style="text-align: right">Class-File API</td>
      <td style="text-align: right">Minor</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>485</strong></td>
      <td>Stream Gatherers</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Core Libs</td>
      <td style="text-align: right">Streams</td>
      <td style="text-align: right">None</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>486</strong></td>
      <td>Permanently Disable the Security Manager</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Security Libs</td>
      <td style="text-align: right">Deprecation</td>
      <td style="text-align: right">Deprecation</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>487</strong></td>
      <td>Scoped Values</td>
      <td style="text-align: right">Fourth Preview</td>
      <td style="text-align: right">Loom</td>
      <td style="text-align: right">Concurrency</td>
      <td style="text-align: right">Minor</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>488</strong></td>
      <td>Primitive Types in Patterns, instanceof and switch</td>
      <td style="text-align: right">Second Preview</td>
      <td style="text-align: right">Amber</td>
      <td style="text-align: right">Language</td>
      <td style="text-align: right">None</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>489</strong></td>
      <td>Vector API</td>
      <td style="text-align: right">Ninth Incubator</td>
      <td style="text-align: right">Panama</td>
      <td style="text-align: right">Vector API</td>
      <td style="text-align: right">Major</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>490</strong></td>
      <td>ZGC: Remove the Non-Generational Mode</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">HotSpot / GC</td>
      <td style="text-align: right">Deprecation</td>
      <td style="text-align: right">Deprecation</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>491</strong></td>
      <td>Synchronize Virtual Threads Without Pinning</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">HotSpot</td>
      <td style="text-align: right">Fix</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>492</strong></td>
      <td>Flexible Constructor Bodies</td>
      <td style="text-align: right">Third Preview</td>
      <td style="text-align: right">Amber</td>
      <td style="text-align: right">New feature</td>
      <td style="text-align: right">None</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>493</strong></td>
      <td>Linking Run-Time Images Without JMODs</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Tools / JLink</td>
      <td style="text-align: right">Performance</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>494</strong></td>
      <td>Module Import Declarations</td>
      <td style="text-align: right">Second Preview</td>
      <td style="text-align: right">Amber</td>
      <td style="text-align: right">Language</td>
      <td style="text-align: right">Minor</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>495</strong></td>
      <td>Simple Source Files and Instance Main Methods</td>
      <td style="text-align: right">Fourth Preview</td>
      <td style="text-align: right">Amber</td>
      <td style="text-align: right">Language</td>
      <td style="text-align: right">Name changes only</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>496</strong></td>
      <td>Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Security Libs</td>
      <td style="text-align: right">Security</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>497</strong></td>
      <td>Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Security Libs</td>
      <td style="text-align: right">Security</td>
      <td style="text-align: right">New feature</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>498</strong></td>
      <td>Warn upon Use of Memory-Access Methods in sun.misc.Unsafe</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">Core Libs</td>
      <td style="text-align: right">Deprecation</td>
      <td style="text-align: right">Deprecation</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>499</strong></td>
      <td>Structured Concurrency</td>
      <td style="text-align: right">Fourth Preview</td>
      <td style="text-align: right">Loom</td>
      <td style="text-align: right">Concurrency</td>
      <td style="text-align: right">None</td>
    </tr>
    <tr>
      <td style="text-align: right"><strong>501</strong></td>
      <td>Deprecate the 32-bit x86 Port for Removal</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right">HotSpot</td>
      <td style="text-align: right">Deprecation</td>
      <td style="text-align: right">Deprecation</td>
    </tr>
  </tbody>
</table>

<h2 id="new-features">New features</h2>

<p>Let’s start with the JEP’s that add brand-new features to Java 24.</p>

<h3 id="hotspot">HotSpot</h3>

<p>Java 24 introduces five new features in <a href="https://openjdk.org/groups/hotspot/">HotSpot</a>:</p>

<ul>
  <li>Generational Shenandoah (Experimental)</li>
  <li>Compact Object Headers (Experimental)</li>
  <li>Late Barrier Expansion for G1</li>
  <li>Ahead-of-Time Class Loading &amp; Linking</li>
  <li>Synchronize Virtual Threads Without Pinning</li>
</ul>

<blockquote>
  <p>The HotSpot JVM is the runtime engine that is developed by Oracle. It translates Java bytecode into machine code for the host operating system’s processor architecture.</p>
</blockquote>

<h4 id="jep-404-generational-shenandoah-experimental">JEP 404: Generational Shenandoah (Experimental)</h4>

<p>The Shenandoah garbage collector is an ultra-low pause time garbage collector. It has been <a href="https://openjdk.org/jeps/379">available for production use since Java 15</a> and has been designed to dramatically reduce garbage collection pause times, regardless of the heap size that is used. It can achieve these low pause times because most of the work is done before the GC pause, in a series of preparation steps. Shenandoah marks and compacts any heap objects eligible for garbage collection, while regular Java user threads are still running.</p>

<p>Java 24 introduces an extension to Shenandoah that maintains separate generations for young and old objects, allowing Shenandoah to collect young objects more frequently. This will result in a significant performance gain for applications running with generational Shenandoah, without sacrificing any of the valuable properties that the garbage collector is already known for.</p>

<p>The reason for handling young and old objects separately stems from the <a href="https://docs.oracle.com/en/java/javase/17/gctuning/garbage-collector-implementation.html#GUID-71D796B3-CBAB-4D80-B5C3-2620E45F6E5D">weak generational hypothesis</a>, which states that young objects tend to die young, while old objects tend to stick around. This means that collecting young objects requires fewer resources and yields more memory, while collecting old objects requires more resources and yields less memory. This is the reason we can improve the performance of applications that use Shenandoah by collecting young objects more frequently.</p>

<h5 id="running-a-workload-with-generational-shenandoah">Running a Workload With Generational Shenandoah</h5>

<p>Shenandoah used to behave in a non-generational way only. Running it required the following command-line configuration:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java ... <span class="nt">-XX</span>:+UseShenandoahGC
</code></pre></div></div>

<p>To run your workload with generational Shenandoah in Java 24, the following configuration is needed:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java ... <span class="nt">-XX</span>:+UseShenandoahGC <span class="nt">-XX</span>:+UnlockExperimentalVMOptions <span class="nt">-XX</span>:ShenandoahGCMode<span class="o">=</span>generational
</code></pre></div></div>

<p>As you can see, generational Shenandoah has been introduced alongside non-generational Shenandoah. In a future release we can expect generational Shenandoah to become the default configuration.</p>

<h5 id="more-information">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/404">JEP 404</a>.</p>

<h4 id="jep-450-compact-object-headers-experimental">JEP 450: Compact Object Headers (Experimental)</h4>

<p>A Java object stored in the heap has metadata, which the HotSpot JVM stores in the object’s header. Object headers are a fixed size, occupying between 96 and 128 bits, depending on how the JVM is configured. Since Java objects are often small (<a href="https://wiki.openjdk.org/display/lilliput/Lilliput+Experiment+Results">typically 256 to 512 bits</a>), object headers can take up over 20% of live data. So reducing the size of object headers can significantly decrease memory footprint and garbage collection pressure. Project Lilliput experiments show a 10%-20% reduction in live data for real-world applications.</p>

<p>JEP 450 proposes to reduce the object header size to 64 bits, by merging the two parts that currently make up the object header: the <em>mark word</em> and the <em>class word</em>.</p>

<h5 id="legacy-object-header">Legacy Object Header</h5>

<p>The mark word comes first, has the size of a machine address, and contains:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Mark Word (normal):
 64                     39                              8    3  0
  [.......................HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH.AAAA.TT]
         (Unused)                      (Hash Code)     (GC Age)(Tag)
</code></pre></div></div>

<p>The class word comes after the mark word. It takes one of two shapes, depending on whether compressed class pointers are enabled:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Class Word (uncompressed):
64                                                               0
 [cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc]
                          (Class Pointer)

Class Word (compressed):
32                               0
 [CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC]
     (Compressed Class Pointer)
</code></pre></div></div>

<p>The class word is never overwritten, which means that an object’s type information is always available, so no additional steps are required to check a type or invoke a method.</p>

<h5 id="compact-object-header">Compact Object Header</h5>

<p>For compact object headers, the division between the mark and class word is removed:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Header (compact):
64                    42                             11   7   3  0
 [CCCCCCCCCCCCCCCCCCCCCCHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHVVVVAAAASTT]
 (Compressed Class Pointer)       (Hash Code)         /(GC Age)^(Tag)
                              (Valhalla-reserved bits) (Self Forwarded Tag)
</code></pre></div></div>

<p>As you can see, the size of the hash code does not change.</p>

<blockquote>
  <p>Note that four bits are reserved for future use by <a href="https://openjdk.org/projects/valhalla/">Project Valhalla</a>.</p>
</blockquote>

<h5 id="future-of-this-feature">Future of This Feature</h5>

<p>This experimental feature will have a broad impact on real-world applications. The code might have inefficiencies, bugs, and unanticipated non-bug behaviors. This feature must therefore be disabled by default and enabled only by explicit user request. We can expect the feature to become enabled by default in later releases and eventually the code for legacy object headers will be removed altogether.</p>

<h5 id="enabling-compact-object-headers">Enabling Compact Object Headers</h5>

<p>Compact object headers can be enabled as follows:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java ... <span class="nt">-XX</span>:+UnlockExperimentalVMOptions <span class="nt">-XX</span>:+UseCompactObjectHeaders
</code></pre></div></div>

<h5 id="more-information-1">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/450">JEP 450</a>.</p>

<h4 id="jep-475-late-barrier-expansion-for-g1">JEP 475: Late Barrier Expansion for G1</h4>

<p>The speed of Java applications has become increasingly important with the growing popularity of cloud-based Java deployments. An effective technique for speeding up Java applications is JIT compilation, but it incurs significant overhead in terms of processing time and memory usage. This is particularly noticeable with the C2 compiler which, through its use of early G1 barrier expansion, accounts for <a href="https://robcasloz.github.io/blog/assets/c2-speed-results.html">up to 20% of the total overhead</a> incurred.</p>

<h5 id="g1-c2-early-barrier-expansion-help-me-out-here">G1? C2? Early Barrier Expansion? Help Me Out Here!</h5>

<p><em>G1</em> has been Java’s <a href="https://openjdk.org/jeps/248">default garbage collector since Java 9</a>. It’s been designed to provide high performance and low pause times for applications with large heaps. It divides the heap into regions and prioritizes garbage collection in regions with the most garbage, hence the name “Garbage-First.” G1 aims to achieve predictable pause times by performing most of its work concurrently with the application threads, minimizing the impact on application performance.</p>

<p>The <em>C2 compiler</em>, also known as the “HotSpot Server Compiler,” is one of the Just-In-Time (JIT) compilers used by the HotSpot JVM in Java. It is designed to optimize and compile Java bytecode into highly optimized machine code at runtime, improving the performance of Java applications. The C2 compiler performs aggressive optimizations, such as inlining, loop unrolling, and escape analysis, to generate efficient native code for performance-critical parts of the application. It is typically used for long-running server applications where performance is crucial.</p>

<p><em>Barrier expansion</em> is the process of inserting or generating additional code (‘barriers’) that manages memory and ensures the correctness of garbage collection. These barriers are typically inserted at specific points in the byte code, such as before or after memory access, to perform tasks like:</p>

<ul>
  <li><em>remembering writes</em>: keeping track of changes to objects, which helps the garbage collector identify which parts of the heap need to be scanned;</li>
  <li><em>maintaining consistency</em>: ensuring that the program’s view of memory remains consistent with the garbage collector’s view, especially during concurrent garbage collection phases;</li>
  <li><em>handling references</em>: managing references between objects, particularly when objects are moved during compaction or evacuation phases.</li>
</ul>

<p><em>Early barrier expansion</em> simply means that these barriers are inserted or generated early in the compilation process, whereas doing this <em>later</em> in the process (as the JEP proposes) would allow for more optimized placement and potentially reduce the overhead associated with these barriers. This can lead to improved performance and more efficient garbage collection.</p>

<h5 id="more-information-2">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/475">JEP 475</a>. It has more details on the barrier expansion process, and how barrier expansion in the (early) <em>bytecode parsing</em> stage differs from barrier expansion in the (late) <em>code emission</em> stage.</p>

<h4 id="jep-483-ahead-of-time-class-loading--linking">JEP 483: Ahead-of-Time Class Loading &amp; Linking</h4>

<p>With features like dynamic class loading, dynamic reflection, dynamic compilation, annotation processing and native code optimization, the Java Platform is a highly dynamic one.
To be able to support these dynamic features, the JVM is forced to do a lot of work during startup, like:</p>

<ul>
  <li>Scanning hundreds of JAR files on disk, while reading and parsing thousands of class files into memory;</li>
  <li>Loading the parsed class data into class objects and linking them together;</li>
  <li>Executing the static initializers of classes, which can create many objects and even perform I/O operations.</li>
</ul>

<p>If the application uses a framework like Spring, then the startup-time discovery of <code class="language-plaintext highlighter-rouge">@Bean</code>, <code class="language-plaintext highlighter-rouge">@Configuration</code>, and related annotations will trigger yet more work.</p>

<p>The process described is performed on demand and optimized for quick execution, allowing many Java programs to start in milliseconds. 
However, larger server applications that utilize web frameworks and various libraries can take seconds or even minutes to launch.
Applications often repeat similar tasks during startup, such as scanning JAR files, loading classes, executing static initializers, and configuring application objects using reflection. 
To enhance startup speed, it’s beneficial to perform some of these tasks proactively rather than waiting until they are needed. 
This approach aligns with the goals of <a href="https://openjdk.org/projects/leyden/">Project Leyden</a>, which strives to advance certain processes to an earlier stage.</p>

<h5 id="ahead-of-time-cache">Ahead-of-Time Cache</h5>

<p>JEP 483, the first JEP out of Project Leyden, proposes to extend the JVM with an <em>ahead-of-time cache</em> to store classes after reading, parsing, loading and linking them.
A created cache for a specific application can be re-used in subsequent runs of that application to improve startup time.</p>

<p>Creating a cache takes two steps. 
First, you should run the application once in a training run, to record its AOT configuration (in this case into the file <code class="language-plaintext highlighter-rouge">app.aotconf</code>):</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:AOTMode<span class="o">=</span>record <span class="nt">-XX</span>:AOTConfiguration<span class="o">=</span>app.aotconf <span class="nt">-cp</span> app.jar com.example.App ...
</code></pre></div></div>

<blockquote>
  <p>Generally speaking, a production run is a good candidate for the training run, as training runs aim to capture application configuration and execution history. In cases where using a production run is impractical (due to activities or accessing databases), it’s recommended to create a synthetic training run that closely resembles production runs, fully configuring itself and testing typical code paths. This can be done by adding a second main class, which invokes the production main class while using a temporary log directory, local network settings, and a mocked database if necessary. You might already have such a main class in the form of an integration test.</p>
</blockquote>

<p>Second, use the configuration to create the cache, in the file <code class="language-plaintext highlighter-rouge">app.aot</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:AOTMode<span class="o">=</span>create <span class="nt">-XX</span>:AOTConfiguration<span class="o">=</span>app.aotconf <span class="nt">-XX</span>:AOTCache<span class="o">=</span>app.aot <span class="nt">-cp</span> app.jar
</code></pre></div></div>

<p>Subsequently, to run the application with the cache:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:AOTCache<span class="o">=</span>app.aot <span class="nt">-cp</span> app.jar com.example.App ...
</code></pre></div></div>

<p>The AOT cache moves the tasks of reading, parsing, loading, and linking (typically performed just-in-time during program execution) to an earlier stage when the cache is created. 
As a result, the program starts up more quickly in the execution phase since its classes are readily accessible from the cache.</p>

<h5 id="performance-improvements-of-up-to-42">Performance Improvements of Up To 42%</h5>

<p>To illustrate this, let’s look at a short pragram that uses the Stream API and thus causes almost 600 JDK classes to be read, parsed, loaded, and linked:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">java.util.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.stream.*</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloStream</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="kt">var</span> <span class="n">words</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"hello"</span><span class="o">,</span> <span class="s">"fuzzy"</span><span class="o">,</span> <span class="s">"world"</span><span class="o">);</span>
        <span class="kt">var</span> <span class="n">greeting</span> <span class="o">=</span> <span class="n">words</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
            <span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">w</span> <span class="o">-&gt;</span> <span class="o">!</span><span class="n">w</span><span class="o">.</span><span class="na">contains</span><span class="o">(</span><span class="s">"z"</span><span class="o">))</span>
            <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">joining</span><span class="o">(</span><span class="s">", "</span><span class="o">));</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">greeting</span><span class="o">);</span>  <span class="c1">// hello, world</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This program runs in 0.031 seconds on JDK 23. 
After doing the small amount of additional work required to create an AOT cache it runs in in 0.018 seconds on JDK 24 — an improvement of 42%. The AOT cache occupies 11.4 megabytes.</p>

<p>For a representative server application, consider <a href="https://github.com/spring-projects/spring-petclinic">Spring PetClinic</a> (v3.2.0). 
It loads and links about 21,000 classes at startup. 
It starts in 4.486 seconds on JDK 23 and in 2.604 seconds on JDK 24 when using an AOT cache — coincidentally also an improvement of 42%. Here the AOT cache occupies 130 megabytes.</p>

<h5 id="more-information-3">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/483">JEP 483</a>.</p>

<h4 id="jep-491-synchronize-virtual-threads-without-pinning">JEP 491: Synchronize Virtual Threads Without Pinning</h4>

<p><a href="https://openjdk.org/jeps/444">Virtual threads</a>, available since Java 21, are lightweight threads that are scheduled by the JVM instead of by the operating system. Creating them and disposing of them is fast and cheap, and millions of them can be created within the same JVM.</p>

<p>A virtual thread goes through several stages in its lifetime:</p>

<ul>
  <li>The virtual thread is <em>created</em> and linked to the code it should run during its lifetime.</li>
  <li>To actually run the code, the virtual thread is <em>mounted</em> on a platform thread, making that platform thread the <em>carrier</em> of the virtual thread.</li>
  <li>After running the code, the virtual thread is <em>unmounted</em> from its carrier and the platform thread is released, so the JDK’s scheduler can mount a different virtual thread on it. Unmounting also happens when a virtual thread performs a blocking operation (such as I/O). When the blocking operation is ready to complete, the virtual thread is submitted back to the JDK’s scheduler, which mounts it on a platform thread again to resume running code.</li>
</ul>

<p>This means that virtual threads are mounted and unmounted frequently, without blocking any platform threads.</p>

<h5 id="pinning">Pinning</h5>

<p>But here’s the catch: a virtual thread cannot unmount from its carrier when it runs code inside a <code class="language-plaintext highlighter-rouge">synchronized</code> block. Consider the class below, which is run by a virtual thread, tracking the number of customers in a store:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">CustomerCounter</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">final</span> <span class="nc">StoreRepository</span> <span class="n">storeRepo</span><span class="o">;</span>
    <span class="kd">private</span> <span class="kt">int</span> <span class="n">customerCount</span><span class="o">;</span>

    <span class="nc">CustomerCounter</span><span class="o">(</span><span class="nc">StoreRepository</span> <span class="n">storeRepo</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">storeRepo</span> <span class="o">=</span> <span class="n">storeRepo</span><span class="o">;</span>
        <span class="n">customerCount</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">synchronized</span> <span class="kt">void</span> <span class="nf">customerEnters</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">customerCount</span> <span class="o">&lt;</span> <span class="n">storeRepo</span><span class="o">.</span><span class="na">fetchCapacity</span><span class="o">())</span> <span class="o">{</span>
            <span class="n">customerCount</span><span class="o">++;</span>
        <span class="o">}</span>
    <span class="o">}</span>

    <span class="kd">synchronized</span> <span class="kt">void</span> <span class="nf">customerExits</span><span class="o">()</span> <span class="o">{</span>
        <span class="n">customerCount</span><span class="o">--;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>If the <code class="language-plaintext highlighter-rouge">storeRepo.fetchCapacity()</code> method call blocks, it would be nice if the running virtual thread would unmount from its carrier, releasing a platform thread for other virtual threads to be mounted. 
But <code class="language-plaintext highlighter-rouge">customerEnters()</code> is <code class="language-plaintext highlighter-rouge">synchronized</code>, and because of this the JVM <em>pins</em> the virtual thread to its carrier, preventing it to be unmounted. 
The result is that both the virtual thread and the underlying OS thread are blocked, until the result from <code class="language-plaintext highlighter-rouge">fetchCapacity()</code> is available.</p>

<h5 id="the-reason-for-pinning">The Reason For Pinning</h5>

<p><code class="language-plaintext highlighter-rouge">synchronized</code> blocks and methods in Java rely on <a href="https://en.wikipedia.org/wiki/Monitor_(synchronization)">monitors</a> to make sure they can be entered by a single thread at the same time. 
Before a thread can run a <code class="language-plaintext highlighter-rouge">synchronized</code> block, it has to acquire the monitor associated with the instance.
The JVM tracks ownership of these monitors on a <em>platform thread</em> level, not on a virtual thread.
Given that information, imagine for a moment that <em>pinning</em> didn’t exist.
Then in theory, virtual thread #1 could unmount in the middle of a <code class="language-plaintext highlighter-rouge">synchronized</code> block, and virtual thread #2 could be mounted on the same platform thread, continuing that same <code class="language-plaintext highlighter-rouge">synchronized</code> block because the carrier thread is the same and still holds the object’s monitor.
Understandably, the JVM actively prevents this situation!</p>

<h5 id="overcoming-pinning">Overcoming Pinning</h5>

<p>So pinning <em>does</em> have a purpose, but frequent pinning for long durations can harm scalability.
Because of this, many libraries have switched to using the more flexible <a href="https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/util/concurrent/locks/package-summary.html"><code class="language-plaintext highlighter-rouge">java.util.concurrent</code> locks</a> instead, which do not pin virtual threads.
But this is a workaround at best, and that’s why JEP 491 proposes to overcome virtual thread pinning.</p>

<p>From Java 24 on, virtual threads can acquire, hold and release monitors, regardless of their carriers.
This also means that switching to different locking mechanisms because of thread pinning is no longer necessary.
Both approaches will perform equally well with virtual threads from now on.</p>

<h5 id="remaining-pinning-cases">Remaining Pinning Cases</h5>

<p>One of the few remaining situations in which a virtual thread will still be pinned, is when it calls native code, which returns to Java code that performs a blocking operation.
In cases like this, the JDK Flight Recorder will record a <a href="https://openjdk.org/jeps/444#JDK-Flight-Recorder-JFR"><code class="language-plaintext highlighter-rouge">jdk.VirtualThreadPinned</code></a> event, should you want to keep track of these situations.</p>

<h5 id="more-information-4">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/491">JEP 491</a>.</p>

<h3 id="security-libs">Security Libs</h3>

<p>Java 24 introduces three new features that are part of the Security Libs:</p>

<ul>
  <li>Key Derivation Function API (Preview)</li>
  <li>Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism</li>
  <li>Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm</li>
</ul>

<h4 id="jep-478-key-derivation-function-api-preview">JEP 478: Key Derivation Function API (Preview)</h4>

<p>As the field of quantum computing advances, traditional cryptographic algorithms are becoming more susceptible to practical attacks. Thus, it is essential for the Java Platform to incorporate Post-Quantum Cryptography (PQC), which can withstand such threats. Java’s long-term goal is to eventually implement Hybrid Public Key Encryption (HPKE), facilitating a seamless transition to quantum-resistant encryption methods. The <a href="https://hanno.codes/2023/09/19/java-21-release-day/#jep-452-key-encapsulation-mechanism-api">KEM API (JEP 452)</a>, included in JDK 21, serves as one component of HPKE and marks Java’s initial move towards HPKE and readiness for post-quantum challenges. This JEP proposes an additional component of HPKE as a next step in this direction: an API for <a href="https://en.wikipedia.org/wiki/Key_derivation_function">Key Derivation Functions</a> (KDFs).</p>

<p>KDF’s are cryptographic algorithms for deriving additional keys from a secret key and other data. A KDF allows keys to be created in a manner that is both secure and reproducible by two parties sharing knowledge of the inputs. Deriving keys is similar to hashing passwords. A KDF employs a keyed hash along with extra entropy from its other inputs to either derive new key material or safely expand existing values into a larger quantity of key material.</p>

<h5 id="operations">Operations</h5>

<p>A key derivation function has two fundamental operations:</p>

<ul>
  <li><em>instantiation and initialization</em>, creating a KDF and initializing it with the appropriate parameters;</li>
  <li><em>derivation</em>, accepting key material and other optional inputs as well as parameters to describe the output, and generating the derived key or data.</li>
</ul>

<p>A new class, <a href="https://cr.openjdk.org/~kdriver/KDF-JEP/javadoc/java.base/javax/crypto/KDF.html"><code class="language-plaintext highlighter-rouge">javax.crypto.KDF</code></a> represents key derivation functions.</p>

<h5 id="code-example">Code Example</h5>

<p>To get an idea of how to use this API, see the code example below (taken from the JEP):</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Create a KDF object for the specified algorithm</span>
<span class="no">KDF</span> <span class="n">hkdf</span> <span class="o">=</span> <span class="no">KDF</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"HKDF-SHA256"</span><span class="o">);</span> 

<span class="c1">// Create an ExtractExpand parameter specification</span>
<span class="nc">AlgorithmParameterSpec</span> <span class="n">params</span> <span class="o">=</span>
    <span class="nc">HKDFParameterSpec</span><span class="o">.</span><span class="na">ofExtract</span><span class="o">()</span>
                     <span class="o">.</span><span class="na">addIKM</span><span class="o">(</span><span class="n">initialKeyMaterial</span><span class="o">)</span>
                     <span class="o">.</span><span class="na">addSalt</span><span class="o">(</span><span class="n">salt</span><span class="o">).</span><span class="na">thenExpand</span><span class="o">(</span><span class="n">info</span><span class="o">,</span> <span class="mi">32</span><span class="o">);</span>

<span class="c1">// Derive a 32-byte AES key</span>
<span class="nc">SecretKey</span> <span class="n">key</span> <span class="o">=</span> <span class="n">hkdf</span><span class="o">.</span><span class="na">deriveKey</span><span class="o">(</span><span class="s">"AES"</span><span class="o">,</span> <span class="n">params</span><span class="o">);</span>

<span class="c1">// Additional deriveKey calls can be made with the same KDF object</span>
</code></pre></div></div>

<h5 id="preview-warning">Preview Warning</h5>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h5 id="more-information-5">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/478">JEP 478</a>.</p>

<h4 id="jep-496-quantum-resistant-module-lattice-based-key-encapsulation-mechanism">JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism</h4>

<p>We mentioned quantum computing advancements before in this article, and with good reason. Public-key based algorithms like Rivest-Shamir-Adleman (RSA) and Diffie-Hellman are more and more at risk of practical quantum computing attacks, but they are still in use by the Java Platform (for things like digitally signing JAR files or establishing secure network connections through TLS). To address this issue, <a href="https://en.wikipedia.org/wiki/Post-quantum_cryptography">quantum-resistant</a> cryptographic algorithms have been invented, and this JEP introduces an implementation of one of those algorithms: the <a href="https://csrc.nist.gov/pubs/fips/203/final">Module-Lattice-Based Key-Encapsulation Mechanism</a> (ML-KEM).</p>

<h5 id="kem-components">KEM Components</h5>

<p>As described in <a href="https://hanno.codes/2023/09/19/java-21-release-day/#jep-452-key-encapsulation-mechanism-api">JEP 452</a>, any key encapsulation mechanism needs the following components:</p>

<ul>
  <li>a <em>key pair generation function</em> that returns a key pair containing a public key and a private key.</li>
  <li>a <em>key encapsulation function</em>, called by the sender, that takes the receiver’s public key and an encryption option; it returns a secret key and a <em>key encapsulation message</em>. The sender sends the key encapsulation message to the receiver.</li>
  <li>a <em>key decapsulation function</em>, called by the receiver, that takes the receiver’s private key and the received key encapsulation message; it returns the secret key.</li>
</ul>

<p>The ML-KEM algorithm provides an implementation of the <code class="language-plaintext highlighter-rouge">KeyPairGenerator</code> API to generate ML-KEM key pairs. To encapsulate and decapsulate keys, an implementation of the KEM API is provided that negotiates shared secret keys based on an ML-KEM key pair. Also provided is an implementation of the <code class="language-plaintext highlighter-rouge">KeyFactory</code> API, that converts ML-KEM keys to and from their encodings.</p>

<p>Furthermore, a new standard algorithm family name (“ML-KEM”) will be defined in the <a href="https://docs.oracle.com/en/java/javase/23/docs/specs/security/standard-names.html">Java Security Standard Algorithm Names Specification</a>. The algorithm comes with three parameter sets (increasing in security, decreasing in performance): 
“ML-KEM-512”, “ML-KEM-768”, and “ML-KEM-1024”. They are represented by the new <code class="language-plaintext highlighter-rouge">NamedParameterSpec</code> constants <code class="language-plaintext highlighter-rouge">ML_KEM_512</code>, <code class="language-plaintext highlighter-rouge">ML_KEM_768</code> and <code class="language-plaintext highlighter-rouge">ML_KEM_1024</code>.</p>

<h5 id="generating-ml-kem-key-pairs">Generating ML-KEM Key Pairs</h5>

<p>You can generate an ML-KEM key pair in one of three ways:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">KeyPairGenerator</span> <span class="n">generator</span> <span class="o">=</span> <span class="nc">KeyPairGenerator</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ML-KEM"</span><span class="o">);</span>
<span class="n">generator</span><span class="o">.</span><span class="na">initialize</span><span class="o">(</span><span class="nc">NamedParameterSpec</span><span class="o">.</span><span class="na">ML_KEM_512</span><span class="o">);</span>
<span class="nc">KeyPair</span> <span class="n">keyPair</span> <span class="o">=</span> <span class="n">generator</span><span class="o">.</span><span class="na">generateKeyPair</span><span class="o">();</span> <span class="c1">// an ML-KEM-512 key pair</span>
</code></pre></div></div>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">KeyPairGenerator</span> <span class="n">generator</span> <span class="o">=</span> <span class="nc">KeyPairGenerator</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ML-KEM"</span><span class="o">);</span>
<span class="nc">KeyPair</span> <span class="n">keyPair</span> <span class="o">=</span> <span class="n">generator</span><span class="o">.</span><span class="na">generateKeyPair</span><span class="o">();</span> <span class="c1">// an ML-KEM-768 key pair by default</span>
</code></pre></div></div>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">KeyPairGenerator</span> <span class="n">generator</span> <span class="o">=</span> <span class="nc">KeyPairGenerator</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ML-KEM-1024"</span><span class="o">);</span>
<span class="nc">KeyPair</span> <span class="n">keyPair</span> <span class="o">=</span> <span class="n">generator</span><span class="o">.</span><span class="na">generateKeyPair</span><span class="o">();</span> <span class="c1">// an ML-KEM-1024 key pair</span>
</code></pre></div></div>

<h5 id="keytool">keytool</h5>

<p>The <code class="language-plaintext highlighter-rouge">keytool</code> command will support generating ML-KEM key pairs and certificates:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>keytool <span class="nt">-keystore</span> ks <span class="nt">-storepass</span> changeit <span class="nt">-genkeypair</span> <span class="nt">-alias</span> ec <span class="se">\</span>
          <span class="nt">-keyalg</span> ec <span class="nt">-dname</span> <span class="nv">CN</span><span class="o">=</span>ec <span class="nt">-ext</span> bc
<span class="nv">$ </span>keytool <span class="nt">-keystore</span> ks <span class="nt">-storepass</span> changeit <span class="nt">-genkeypair</span> <span class="nt">-alias</span> mlkem <span class="se">\</span>
          <span class="nt">-keyalg</span> ML-KEM <span class="nt">-groupname</span> ML-KEM-768 <span class="nt">-dname</span> <span class="nv">CN</span><span class="o">=</span>ML-KEM <span class="nt">-signer</span> ec
</code></pre></div></div>

<p>The parameter-set name (<code class="language-plaintext highlighter-rouge">ML-KEM-768</code>) can also be provided directly with the <code class="language-plaintext highlighter-rouge">-keyalg</code> option:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>keytool <span class="nt">-keystore</span> ks <span class="nt">-storepass</span> changeit <span class="nt">-genkeypair</span> <span class="nt">-alias</span> mlkem2 <span class="se">\</span>
          <span class="nt">-keyalg</span> ML-KEM-768 <span class="nt">-dname</span> <span class="nv">CN</span><span class="o">=</span>ML-KEM2 <span class="nt">-signer</span> ec
</code></pre></div></div>

<h5 id="encapsulating-and-decapsulating-keys">Encapsulating and Decapsulating Keys</h5>

<p>You can use the ML-KEM <code class="language-plaintext highlighter-rouge">KEM</code> implementation to negotiate a shared secret key.</p>

<p>For example, a sender can call the encapsulation function to get a secret key and a key encapsulation message:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">KEM</span> <span class="n">ks</span> <span class="o">=</span> <span class="no">KEM</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ML-KEM"</span><span class="o">);</span>
<span class="no">KEM</span><span class="o">.</span><span class="na">Encapsulator</span> <span class="n">enc</span> <span class="o">=</span> <span class="n">ks</span><span class="o">.</span><span class="na">newEncapsulator</span><span class="o">(</span><span class="n">publicKey</span><span class="o">);</span>
<span class="no">KEM</span><span class="o">.</span><span class="na">Encapsulated</span> <span class="n">encap</span> <span class="o">=</span> <span class="n">enc</span><span class="o">.</span><span class="na">encapsulate</span><span class="o">();</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">msg</span> <span class="o">=</span> <span class="n">encap</span><span class="o">.</span><span class="na">encapsulation</span><span class="o">();</span>     <span class="c1">// send this to receiver</span>
<span class="nc">SecretKey</span> <span class="n">sks</span> <span class="o">=</span> <span class="n">encap</span><span class="o">.</span><span class="na">key</span><span class="o">();</span>
</code></pre></div></div>

<p>A receiver can then call the decapsulation function to recover the secret key from the key encapsulation message sent by the sender:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">byte</span><span class="o">[]</span> <span class="n">msg</span> <span class="o">=</span> <span class="o">...;</span>                       <span class="c1">// received from sender</span>
<span class="no">KEM</span> <span class="n">kr</span> <span class="o">=</span> <span class="no">KEM</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ML-KEM"</span><span class="o">);</span>
<span class="no">KEM</span><span class="o">.</span><span class="na">Decapsulator</span> <span class="n">dec</span> <span class="o">=</span> <span class="n">kr</span><span class="o">.</span><span class="na">newDecapsulator</span><span class="o">(</span><span class="n">privateKey</span><span class="o">);</span>
<span class="nc">SecretKey</span> <span class="n">skr</span> <span class="o">=</span> <span class="n">dec</span><span class="o">.</span><span class="na">decapsulate</span><span class="o">(</span><span class="n">msg</span><span class="o">);</span>
</code></pre></div></div>

<p>Both <code class="language-plaintext highlighter-rouge">sks</code> and <code class="language-plaintext highlighter-rouge">skr</code> now contain the same key material, which is known only to the sender and the receiver.</p>

<h5 id="more-information-6">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/496">JEP 496</a>.</p>

<h4 id="jep-497-quantum-resistant-module-lattice-based-digital-signature-algorithm">JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm</h4>

<p>For the exact same reason as the previous JEP, this one introduces an implementation of a different quantum-resistant algorithm: the <a href="https://csrc.nist.gov/pubs/fips/204/final">Module-Lattice-Based Digital Signature Algorithm</a> (ML-DSA).</p>

<p>The ML-DSA algorithm provides an implementation of both the <code class="language-plaintext highlighter-rouge">KeyPairGenerator</code> API (to generate ML-DSA key pairs) and the <code class="language-plaintext highlighter-rouge">Signature</code> API (to sign and verify ML-DSA signatures). Also provided is an implementation of the <code class="language-plaintext highlighter-rouge">KeyFactory</code> API, that converts ML-DSA keys to and from their encodings.</p>

<p>Furthermore, a new standard algorithm family name (“ML-DSA”) will be defined in the <a href="https://docs.oracle.com/en/java/javase/23/docs/specs/security/standard-names.html">Java Security Standard Algorithm Names Specification</a>. The algorithm comes with three parameter sets (increasing in security, decreasing in performance): 
“ML-DSA-44”, “ML-DSA-65”, and “ML-DSA-87”. They are represented by the new <code class="language-plaintext highlighter-rouge">NamedParameterSpec</code> constants <code class="language-plaintext highlighter-rouge">ML_DSA_44</code>, <code class="language-plaintext highlighter-rouge">ML_DSA_65</code> and <code class="language-plaintext highlighter-rouge">ML_DSA_87</code>.</p>

<h5 id="generating-ml-dsa-key-pairs">Generating ML-DSA Key Pairs</h5>

<p>You can generate an ML-DSA key pair in one of three ways:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">KeyPairGenerator</span> <span class="n">generator</span> <span class="o">=</span> <span class="nc">KeyPairGenerator</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ML-DSA"</span><span class="o">);</span>
<span class="n">generator</span><span class="o">.</span><span class="na">initialize</span><span class="o">(</span><span class="nc">NamedParameterSpec</span><span class="o">.</span><span class="na">ML_DSA_44</span><span class="o">);</span>
<span class="nc">KeyPair</span> <span class="n">keyPair</span> <span class="o">=</span> <span class="n">generator</span><span class="o">.</span><span class="na">generateKeyPair</span><span class="o">();</span> <span class="c1">// an ML-DSA-44 key pair</span>
</code></pre></div></div>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">KeyPairGenerator</span> <span class="n">generator</span> <span class="o">=</span> <span class="nc">KeyPairGenerator</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ML-DSA"</span><span class="o">);</span>
<span class="nc">KeyPair</span> <span class="n">keyPair</span> <span class="o">=</span> <span class="n">generator</span><span class="o">.</span><span class="na">generateKeyPair</span><span class="o">();</span> <span class="c1">// an ML-DSA-65 key pair by default</span>
</code></pre></div></div>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">KeyPairGenerator</span> <span class="n">generator</span> <span class="o">=</span> <span class="nc">KeyPairGenerator</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ML-DSA-87"</span><span class="o">);</span>
<span class="nc">KeyPair</span> <span class="n">keyPair</span> <span class="o">=</span> <span class="n">generator</span><span class="o">.</span><span class="na">generateKeyPair</span><span class="o">();</span> <span class="c1">// an ML-DSA-87 key pair</span>
</code></pre></div></div>

<h5 id="keytool-1">keytool</h5>

<p>The <code class="language-plaintext highlighter-rouge">keytool</code> command will support generating ML-DSA key pairs and certificates:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>keytool <span class="nt">-keystore</span> ks <span class="nt">-storepass</span> changeit <span class="nt">-genkeypair</span> <span class="nt">-alias</span> mldsa <span class="se">\</span>
          <span class="nt">-keyalg</span> ML-DSA <span class="nt">-groupname</span> ML-DSA-65 <span class="nt">-dname</span> <span class="nv">CN</span><span class="o">=</span>ML-DSA

<span class="nv">$ </span>keytool <span class="nt">-keystore</span> ks <span class="nt">-storepass</span> changeit <span class="nt">-genkeypair</span> <span class="nt">-alias</span> mldsa <span class="se">\</span>
          <span class="nt">-keyalg</span> ML-DSA-65 <span class="nt">-dname</span> <span class="nv">CN</span><span class="o">=</span>ML-DSA2
</code></pre></div></div>

<p>The parameter-set name (<code class="language-plaintext highlighter-rouge">ML-DSA-65</code>) can also be provided directly with the <code class="language-plaintext highlighter-rouge">-keyalg</code> option:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>keytool <span class="nt">-keystore</span> ks <span class="nt">-storepass</span> changeit <span class="nt">-genkeypair</span> <span class="nt">-alias</span> mldsa <span class="se">\</span>
          <span class="nt">-keyalg</span> ML-DSA-65 <span class="nt">-dname</span> <span class="nv">CN</span><span class="o">=</span>ML-DSA2
</code></pre></div></div>

<h5 id="signing-with-ml-dsa-keys">Signing with ML-DSA Keys</h5>

<p>You can use the ML-DSA Signature implementation to sign and verify ML-DSA signatures.</p>

<p>For example, to sign a message using a private key:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">byte</span><span class="o">[]</span> <span class="n">msg</span> <span class="o">=</span> <span class="o">...;</span>
<span class="nc">Signature</span> <span class="n">ss</span> <span class="o">=</span> <span class="nc">Signature</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ML-DSA"</span><span class="o">);</span>
<span class="n">ss</span><span class="o">.</span><span class="na">initSign</span><span class="o">(</span><span class="n">privateKey</span><span class="o">);</span>
<span class="n">ss</span><span class="o">.</span><span class="na">update</span><span class="o">(</span><span class="n">msg</span><span class="o">);</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">sig</span> <span class="o">=</span> <span class="n">ss</span><span class="o">.</span><span class="na">sign</span><span class="o">();</span>
</code></pre></div></div>

<p>To verify a signature with a public key:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">byte</span><span class="o">[]</span> <span class="n">msg</span> <span class="o">=</span> <span class="o">...;</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">sig</span> <span class="o">=</span> <span class="o">...;</span>
<span class="nc">Signature</span> <span class="n">sv</span> <span class="o">=</span> <span class="nc">Signature</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ML-DSA"</span><span class="o">);</span>
<span class="n">sv</span><span class="o">.</span><span class="na">initVerify</span><span class="o">(</span><span class="n">publicKey</span><span class="o">);</span>
<span class="n">sv</span><span class="o">.</span><span class="na">update</span><span class="o">(</span><span class="n">msg</span><span class="o">);</span>
<span class="kt">boolean</span> <span class="n">verified</span> <span class="o">=</span> <span class="n">sv</span><span class="o">.</span><span class="na">verify</span><span class="o">(</span><span class="n">sig</span><span class="o">);</span>
</code></pre></div></div>

<h5 id="more-information-7">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/497">JEP 497</a>.</p>

<h3 id="tools">Tools</h3>

<p>Java 24 contains a single feature that is part of the JLink tool:</p>

<ul>
  <li>Linking Run-Time Images Without JMODs</li>
</ul>

<h4 id="jep-493-linking-run-time-images-without-jmods">JEP 493: Linking Run-Time Images Without JMODs</h4>

<p>In cloud environments, container images that include an installed JDK are frequently copied over the network from container registries. 
Reducing the size of the JDK would improve the efficiency of these operations.
This is why the <a href="https://dev.java/learn/jlink/"><code class="language-plaintext highlighter-rouge">jlink</code></a> tool can now create custom run-time images without using the JDK’s JMOD files.
This allows users to link a run-time image from modules, regardless of their source (be it JMOD files, modular JARs or part of a run-time image linked previously).</p>

<h5 id="redundancy">Redundancy</h5>

<p>An installed JDK consists of a <em>run-time image</em> and a set of <em>packaged modules</em> in the JMOD format, for each module in the run-time image.
<code class="language-plaintext highlighter-rouge">jlink</code> uses the JMOD files when creating custom run-time images.
In fact, the run-time image in the JDK is a result from this very process.
That means that every resource in the JDK’s run-time image is also present in one of the JMOD files, which makes an installed JDK suffer from <em>redundancy</em>.
The JMOD files account for about 25% of the JDK’s total size.
If <code class="language-plaintext highlighter-rouge">jlink</code> could be changed to extract resources from the run-time image itself, we could dramatically reduce the size of the JDK by simply omitting these JMOD files.</p>

<h5 id="build-a-jdk-with---enable-linkable-runtime">Build a JDK With <code class="language-plaintext highlighter-rouge">--enable-linkable-runtime</code></h5>

<p>The option <code class="language-plaintext highlighter-rouge">--enable-linkable-runtime</code> builds a JDK whose <code class="language-plaintext highlighter-rouge">jlink</code> tool can create run-time images without using JMOD files.
The resulting JDK will have no <code class="language-plaintext highlighter-rouge">jmods</code> directory, which means it’s about 25% smaller than before.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>configure <span class="o">[</span> ... other options ... <span class="o">]</span> <span class="nt">--enable-linkable-runtime</span>
<span class="nv">$ </span>make images
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">jlink</code> tool in any JDK build can consume both JMOD files and modular JAR files. 
In addition, in JDK builds with this feature enabled, <code class="language-plaintext highlighter-rouge">jlink</code> can consume modules from the run-time image of which it is part. 
The <code class="language-plaintext highlighter-rouge">--help</code> output of <code class="language-plaintext highlighter-rouge">jlink</code> shows whether it has this capability:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>jlink <span class="nt">--help</span>
Usage: jlink &lt;options&gt; <span class="nt">--module-path</span> &lt;modulepath&gt; <span class="nt">--add-modules</span> &lt;module&gt;[,&lt;module&gt;...]
...
Capabilities:
      Linking from run-time image enabled
</code></pre></div></div>

<p>So this new capability can be enabled only when building a JDK.
This also means that any <code class="language-plaintext highlighter-rouge">jlink</code> invocation that wants to make use of it doesn’t need any additional options — it can remain exactly the same.
From Java 24 on, <code class="language-plaintext highlighter-rouge">jlink</code> will use JMOD files if it can find them on the module path.
It will consume modules from the run-time image only if the module <code class="language-plaintext highlighter-rouge">java.base</code> is not found on the module path. 
Any other modules must still be specified to <code class="language-plaintext highlighter-rouge">jlink</code> via the <code class="language-plaintext highlighter-rouge">--module-path</code> option.</p>

<h5 id="not-enabled-by-default">Not enabled by default</h5>

<p>This feature is currently not enabled by default, so the default JDK build configuration will remain as it is today.
The resulting JDK will contain JMOD files like before and its <code class="language-plaintext highlighter-rouge">jlink</code> tool will not be able to operate without them. 
Whether the JDK build that you get from your preferred vendor contains this feature is up to that vendor.
Note that the JEP also states that the feature may be enabled by default in a future release.</p>

<h5 id="more-information-8">More Information</h5>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/493">JEP 493</a>.</p>

<h2 id="repreviews-and-finalizations">Repreviews and finalizations</h2>

<p>Now it’s time to take a look at a few features that might already be familiar to you, because they were introduced in a previous version of Java. They have been repreviewed (or finalized) in Java 24, with only minor changes compared to Java 23 in most cases. Therefore, to avoid a very lengthy article, we’ll outline these changes and link to a previous article for a full feature description, should you wish to refresh your memory.</p>

<h3 id="jep-484-class-file-api">JEP 484: Class-File API</h3>

<p>Java frameworks often use bytecode transformation to add functionality, relying on libraries like <a href="https://asm.ow2.io/">ASM</a> or <a href="https://www.javassist.org/">Javassist</a>. However, the JDK’s six-month release cycle can outpace these libraries, causing compatibility issues. JEP 484 addresses this by proposing a standard class-file API that evolves with the JDK, ensuring up-to-date class file processing.</p>

<h4 id="whats-different-from-java-23">What’s Different From Java 23?</h4>

<p>A few minor things changed to the API, based on feedback from the second preview stage. These changes mainly include the removal of a few fields, methods and interfaces, and the renaming of various enum values, fields and methods. The JEP includes <a href="https://openjdk.org/jeps/484#Changes">a detailed list</a> on these changes.</p>

<h4 id="more-information-9">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/484">JEP 484</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-466-class-file-api-second-preview">full feature description</a> from a previous article.</p>

<h3 id="jep-485-stream-gatherers">JEP 485: Stream Gatherers</h3>

<p>The Stream API offers a relatively diverse but predetermined range of intermediate operations, including mapping, filtering, sorting and more. JEP 485 introduces <em>stream gatherers</em>, which allow developers to define their own custom intermediate stream operations, so they can transform streams in their own preferred ways.</p>

<h4 id="whats-different-from-java-23-1">What’s Different From Java 23?</h4>

<p>Nothing was changed, apart from the fact that the API is now finalized in Java 24.</p>

<h4 id="more-information-10">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/485">JEP 485</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-473-stream-gatherers-second-preview">full feature description</a> from a previous article.</p>

<h3 id="jep-487-scoped-values-fourth-preview">JEP 487: Scoped Values (Fourth Preview)</h3>

<p><em>Scoped values</em> enable the sharing of immutable data within and across threads. 
They are preferred to thread-local variables, especially when using a large number of (virtual) threads.</p>

<h4 id="whats-different-from-java-23-2">What’s Different From Java 23?</h4>

<p>A single change was made to the API compared to Java 23:</p>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">callWhere</code> and <code class="language-plaintext highlighter-rouge">runWhere</code> methods were removed from the <code class="language-plaintext highlighter-rouge">ScopedValue</code> class, which means that the entire API is now fluent. The exact same behavior can be obtained by chaining <code class="language-plaintext highlighter-rouge">ScopedValue.where()</code> with <code class="language-plaintext highlighter-rouge">run(Runnable)</code> or <code class="language-plaintext highlighter-rouge">call(Callable)</code>.</li>
</ul>

<h4 id="preview-warning-1">Preview Warning</h4>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-11">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/487">JEP 487</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-481-scoped-values-third-preview">full feature description</a> from a previous article.</p>

<h3 id="jep-488-primitive-types-in-patterns-instanceof-and-switch-second-preview">JEP 488: Primitive Types in Patterns, instanceof and switch (Second Preview)</h3>

<p>Pattern matching now supports primitive types in all pattern contexts. On top of that, the <code class="language-plaintext highlighter-rouge">instanceof</code> and <code class="language-plaintext highlighter-rouge">switch</code> constructs have been extended to also work with all primitive types.</p>

<h4 id="whats-different-from-java-23-3">What’s Different From Java 23?</h4>

<p>Compared to the preview version of this feature in Java 22, nothing was changed or added. JEP 488 simply exists to gather more feedback from users.</p>

<h4 id="preview-warning-2">Preview Warning</h4>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-12">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/488">JEP 488</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-455-primitive-types-in-patterns-instanceof-and-switch-preview">full feature description</a> from a previous article.</p>

<h3 id="jep-489-vector-api-ninth-incubator">JEP 489: Vector API (Ninth Incubator)</h3>

<p>The Vector API makes it possible to express vector computations that reliably compile at runtime to optimal vector instructions. 
This means that these computations will significantly outperform equivalent scalar computations on the supported CPU architectures (x64 and AArch64).</p>

<h4 id="whats-different-from-java-23-4">What’s Different From Java 23?</h4>

<p>The following changes were made to the Vector API compared to Java 23:</p>

<ul>
  <li>A new variation of the <code class="language-plaintext highlighter-rouge">selectFrom</code> cross-lane operation now accepts two input vectors, which serve as a lookup table;</li>
  <li>The <code class="language-plaintext highlighter-rouge">selectFrom</code> and <code class="language-plaintext highlighter-rouge">rearrange</code> cross-lane operations now wrap indexes rather than check for out-of-bounds indexes, making these operations significantly faster.</li>
  <li>Transcendental and trigonometric lanewise operations on ARM and RISC-V are now implemented via intrinsics which call out to the <a href="https://sleef.org/">SIMD Library for Evaluating Elementary Functions (SLEEF)</a>.</li>
  <li>The new value-based class <a href="https://download.java.net/java/early_access/jdk24/docs/api/jdk.incubator.vector/jdk/incubator/vector/Float16.html">Float16</a> represents 16-bit floating-point numbers in the <a href="https://en.wikipedia.org/wiki/Half-precision_floating-point_format">IEEE 754 binary16</a> format.</li>
  <li>The arithmetic integral lanewise operations now include saturating unsigned addition and subtraction, saturating signed addition and subtraction, and unsigned maximum and minimum.</li>
</ul>

<p>The Vector API will keep incubating until necessary features of Project Valhalla become available as preview features. When that happens, the Vector API will be adapted to use them, and it will be promoted from incubation to preview.</p>

<h4 id="more-information-13">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/489">JEP 489</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-469-vector-api-eighth-incubator">full feature description</a> from a previous article.</p>

<h3 id="jep-492-flexible-constructor-bodies-third-preview">JEP 492: Flexible Constructor Bodies (Third Preview)</h3>

<p>Flexible constructor bodies allow statements to appear before an explicit constructor invocation, like <code class="language-plaintext highlighter-rouge">super(..)</code> or <code class="language-plaintext highlighter-rouge">this(..)</code>. The statements cannot reference the instance under construction, but they can initialize its fields. Initializing fields before invoking another constructor makes a class more reliable when methods are overridden.</p>

<h4 id="preview-warning-3">Preview Warning</h4>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="whats-different-from-java-23-5">What’s Different From Java 23?</h4>

<p>Compared to the preview version of this feature in Java 23, no significant changes were made. JEP 492 simply exists to gather more feedback from users.</p>

<h4 id="more-information-14">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/492">JEP 492</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-482-flexible-constructor-bodies-second-preview">full feature description</a> from a previous article.</p>

<h3 id="jep-494-module-import-declarations-second-preview">JEP 494: Module Import Declarations (Second Preview)</h3>

<p>Module import declarations import all of the public top-level classes and interfaces in the packages exported by that module. They are a shorter alternative for listing many imports that originate from the same root package.</p>

<h4 id="whats-different-from-java-23-6">What’s Different From Java 23?</h4>

<p>This feature is repreviewed in Java 24, with two additions:</p>

<ul>
  <li>The restriction that no module is able to declare a transitive dependency on the <code class="language-plaintext highlighter-rouge">java.base</code> module is lifted, and the declaration of the <code class="language-plaintext highlighter-rouge">java.se</code> module to transitively require the <code class="language-plaintext highlighter-rouge">java.base</code> module is revised. With these changes, importing the <code class="language-plaintext highlighter-rouge">java.se</code> module will import the entire Java SE API on demand.</li>
  <li>Type-import-on-demand declarations to shadow module import declarations are now allowed.</li>
</ul>

<h4 id="more-information-15">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/494">JEP 494</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-476-module-import-declarations-preview">full feature description</a> from a previous article.</p>

<h3 id="jep-495-simple-source-files-and-instance-main-methods-fourth-preview">JEP 495: Simple Source Files and Instance Main Methods (Fourth Preview)</h3>

<p>Simple source files allow developers to write Java programs without the need to explicitly declare a class. They can contain ‘instance main methods’: a shorter form of the classic <code class="language-plaintext highlighter-rouge">main()</code> method without requiring program arguments or imports. These two features simplify the process of writing small programs and scripts by reducing boilerplate code.</p>

<h4 id="whats-different-from-java-23-7">What’s Different From Java 23?</h4>

<p>The two features in this JEP didn’t change in Java 24; however, the feature that used to be known as ‘implicitly declared classes’ was renamed to ‘simple source files’.</p>

<h4 id="more-information-16">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/495">JEP 495</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-477-implicitly-declared-classes-and-instance-main-methods-third-preview">full feature description</a> from a previous article.</p>

<h3 id="jep-499-structured-concurrency-fourth-preview">JEP 499: Structured Concurrency (Fourth Preview)</h3>

<p><em>Structured concurrency</em> treats groups of related tasks running in different threads as a single unit of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability.</p>

<h4 id="whats-different-from-java-23-8">What’s Different From Java 23?</h4>

<p>Nothing was changed, the API is re-previewed in Java 24 to give more time for feedback from real world usage.</p>

<p>However, significant API changes are scheduled to appear in a future Java release.
A <code class="language-plaintext highlighter-rouge">StructuredTaskScope</code> will then be opened via static factory methods rather than through public constructors. The zero-parameter <code class="language-plaintext highlighter-rouge">open()</code> factory method will cover the common case by creating a <code class="language-plaintext highlighter-rouge">StructuredTaskScope</code> that waits for all subtasks to succeed or any subtask to fail. Other policies and outcomes can be implemented by providing an appropriate <a href="https://download.java.net/java/early_access/loom/docs/api/java.base/java/util/concurrent/StructuredTaskScope.Joiner.html"><code class="language-plaintext highlighter-rouge">Joiner</code></a> to one of the richer <code class="language-plaintext highlighter-rouge">open(Joiner)</code> factory methods.</p>

<p>If you’re interested in the future of this feature, <a href="https://openjdk.org/jeps/8340343">JEP draft #8340343</a> has more details on these upcoming API changes.</p>

<h4 id="more-information-17">More Information</h4>

<p>If you prefer to get more information on the current state of this feature, then read <a href="https://openjdk.org/jeps/499">JEP 499</a> or the <a href="https://hanno.codes/2024/09/17/java-23-has-arrived/#jep-480-structured-concurrency-third-preview">full feature description</a> from a previous article.</p>

<h2 id="deprecations--restrictions">Deprecations &amp; Restrictions</h2>

<p>Java 24 also deprecates a few older features that weren’t used that much and restricts a few other features that came with certain risks. Let’s see which ones were involved in this effort to improve stability.</p>

<h3 id="jep-472-prepare-to-restrict-the-use-of-jni">JEP 472: Prepare to Restrict the Use of JNI</h3>

<p>The Java Native Interface has been the factory standard of invoking foreign functions (outside of the JVM but on the same machine) for many years now. In Java 22 a more modern approach became available: the <a href="https://hanno.codes/2024/03/19/java-22-is-here/#jep-454-foreign-function--memory-api">Foreign Function &amp; Memory API</a>. Although the new FFM API is the preferred alternative to JNI, that doesn’t mean that JNI will be phased out. On the contrary, the Java language designers want to make sure that migrating from one to the other can be done easily. To make that happen, this JEP introduces certain warnings to JNI to mirror the warnings that the FFM API already produces.</p>

<p>To be more precise, calling native code via JNI requires you to load a native library first and link a Java construct to a function in that library. JEP 472 will add the <a href="https://openjdk.org/jeps/454#Safety">restrictions</a> that the FFM API already imposes on these loading and linking steps to JNI also. All warnings of this type aim to prepare developers for a future release that ensures <a href="https://openjdk.org/jeps/8305968">integrity by default</a> by uniformly restricting JNI and the FFM API.</p>

<h4 id="more-information-18">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/472">JEP 472</a>.</p>

<h3 id="jep-486-permanently-disable-the-security-manager">JEP 486: Permanently Disable the Security Manager</h3>

<p>The Security Manager has not been the primary method for securing client-side Java code for many years and is seldom used for server-side code. It is also costly to maintain. Consequently, it was deprecated for removal in Java 17 via <a href="https://openjdk.org/jeps/411">JEP 411</a>. JEP 486 takes the next logical step: developers are now prevented from enabling the Security Manager at all. The Java Language Designers feel this is a safe step to take, as the deprecation in Java 17 hardly had any impact. The Security Manager API will be removed in a future release.</p>

<h4 id="ok-but-what-exactly-is-the-security-manager">OK, But What Exactly <em>Is</em> the Security Manager?</h4>

<p>That is a fair question, because it has rarely been used. The Security Manager, a feature since Java’s first release, operates on <em>the principle of least privilege</em>: code is untrusted by default, so it cannot access resources such as the filesystem or the network. This restricts code access to resources unless explicitly granted permission. Despite its theoretical benefits, its complexity has led to it being rarely used and has always been disabled by default. The least-privilege model adds significant complexity to Java Platform libraries, requiring over 1,000 methods to check permissions and over 1,200 methods to elevate privileges when the Security Manager is enabled.</p>

<h4 id="more-information-19">More Information</h4>

<p>For more information on this change, read <a href="https://openjdk.org/jeps/486">JEP 486</a>.</p>

<h3 id="jep-490-zgc-remove-the-non-generational-mode">JEP 490: ZGC: Remove the Non-Generational Mode</h3>

<p>The Z Garbage Collector (ZGC) is a scalable, low-latency garbage collector. It has been <a href="https://openjdk.org/jeps/377">available for production use since Java 15</a> and has been designed to keep pause times consistent and short, even for very large heaps. It uses techniques like region-based memory management and compaction to achieve this.</p>

<p>Java 21 introduced <a href="https://openjdk.org/jeps/439">an extension to ZGC</a> that maintains separate <em>generations</em> for young and old objects, allowing ZGC to collect young objects (which tend to die young) more frequently. This will result in a significant performance gain for applications running with generational ZGC, without sacrificing any of the valuable properties that the Z garbage collector is already known for. Java 23 made generational mode the default mode for ZGC and deprecated non-generational mode. Java 24 removes non-generational mode altogether.</p>

<h4 id="how-do-the-zgc-command-line-options-work-after-this-change">How Do the ZGC Command-Line Options Work After This Change?</h4>

<p>In Java 23, the following command would use generational mode by default:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:+UseZGC ...
</code></pre></div></div>

<p>This behavior is still the same in Java 24. Also, in Java 24, if you would run Java with the now-obsolete option <code class="language-plaintext highlighter-rouge">ZGenerational</code>…</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:+UseZGC <span class="nt">-XX</span>:-ZGenerational ...
</code></pre></div></div>

<p>…an obsolete-option warning will be printed.</p>

<h4 id="more-information-20">More Information</h4>

<p>For more information on this feature, read <a href="https://openjdk.org/jeps/490">JEP 490</a>.</p>

<h3 id="jep-498-warn-upon-use-of-memory-access-methods-in-sunmiscunsafe">JEP 498: Warn upon Use of Memory-Access Methods in sun.misc.Unsafe</h3>

<p>The <code class="language-plaintext highlighter-rouge">sun.misc.Unsafe</code> class contains 87 methods to perform low-level operations, such as accessing off-heap memory.
The class is aptly named: using its methods without performing the necessary safety checks can lead to undefined behaviour and to the JVM crashing.
They were meant exclusively for use within the JDK, but back in 2002 when the class was introduced the <a href="https://openjdk.org/projects/jigsaw/">module system</a> wasn’t around yet and so there was no way to prevent the class from being used outside the JDK.
Thus, the memory-access methods in <code class="language-plaintext highlighter-rouge">sun.misc.Unsafe</code> became a valuable tool for library developers seeking greater power and performance than what standard APIs could provide.</p>

<p>Two standard APIs have emerged in recent years that are far better alternatives to these problematic methods:</p>

<ul>
  <li><a href="https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/invoke/VarHandle.html"><code class="language-plaintext highlighter-rouge">java.lang.invoke.VarHandle</code></a>, to manipulate on-heap memory safely and efficiently;</li>
  <li><a href="https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/foreign/MemorySegment.html"><code class="language-plaintext highlighter-rouge">java.lang.foreign.MemorySegment</code></a>, to access off-heap memory safely and efficiently.</li>
</ul>

<p>Given the situation, Java 23 already deprecated the memory-access methods, which led to Java generating <em>compile-time</em> warnings whenever these methods were used. JEP 490 extends this behavior by also generating <em>run-time</em> warnings for any use of these methods.</p>

<p>JDK 24 will, by default, issue a warning on the first occasion that any memory-access method is used, whether directly or via reflection. That is, it will issue at most one warning regardless of which memory-access methods are used and how many times any particular method is used. This will alert application developers and users to the forthcoming removal of the methods, and the need to upgrade libraries. An example of the warning is:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::setMemory has been called by com.foo.bar.Server (file:/tmp/foobarserver/thing.jar)
WARNING: Please consider reporting this to the maintainers of com.foo.bar.Server
WARNING: sun.misc.Unsafe::setMemory will be removed in a future release
</code></pre></div></div>

<p>A future release of Java will start throwing exceptions in these situations. In an even later Java release the methods will be removed entirely. According to the JEP text the entire process won’t be completed until after the release of JDK 26, giving developers ample time to adjust to the new situation.</p>

<h4 id="more-information-21">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/498">JEP 498</a>. It has more details on the targeted methods, their alternatives from <code class="language-plaintext highlighter-rouge">VarHandle</code> and <code class="language-plaintext highlighter-rouge">MemorySegment</code> and how to configure the deprecation warnings with the new command-line option <code class="language-plaintext highlighter-rouge">--sun-misc-unsafe-memory-access</code> (to promote the warnings to <code class="language-plaintext highlighter-rouge">UnsupportedOperationException</code>s already, for example). It also provides a few migration examples.</p>

<h3 id="jep-501-deprecate-the-32-bit-x86-port-for-removal">JEP 501: Deprecate the 32-bit x86 Port for Removal</h3>

<p>Supporting multiple platforms has been the focus of the Java ecosystem since the beginning. 
But older platforms cannot be supported indefinitely, and that is one of the reasons why the 32-bit x86 (Linux) port is now scheduled for removal.
The effort that was required to maintain this port exceeded its advantages. Keeping it up-to-date with new features like Loom, the Foreign Function &amp; Memory API (FFM), the Vector API, and late GC barrier expansion represented a significant cost, so it is now deprecated.</p>

<p>Configuring a 32-bit x86 build will now fail on JDK 24.
This error can be suppressed by using the new build configuration option <code class="language-plaintext highlighter-rouge">--enable-deprecated-ports=yes</code>.
This means 32-bit users can still use JDK 24; however a future release will actually remove the support, and by that time the affected users are expected to have migrated to 64-bit JVMs.</p>

<h4 id="more-information-22">More Information</h4>

<p>For more information on this deprecation, read <a href="https://openjdk.org/jeps/501">JEP 501</a>.</p>

<h3 id="jep-479-remove-the-windows-32-bit-x86-port">JEP 479: Remove the Windows 32-bit x86 Port</h3>

<p>This JEP removes the Windows 32-bit x86 port, which was to be expected after <a href="https://hanno.codes/2023/09/19/java-21-release-day/#jep-449-deprecate-the-windows-32-bit-x86-port-for-removal">its deprecation in Java 21</a>. This is due to the fact that Windows 10, the last Windows operating system to support 32-bit operation, <a href="https://learn.microsoft.com/lifecycle/products/windows-10-home-and-pro">will reach end-of-life in October 2025</a>. On top of that, the implementation of virtual threads on Windows 32-bit x86 is rudimentary to say the least: it uses a single platform thread for each virtual thread, effectively rendering the feature useless on this platform. So it’s time to say goodbye to this port!</p>

<h4 id="more-information-23">More Information</h4>

<p>For more information on this removal, read <a href="https://openjdk.org/jeps/479">JEP 479</a>.</p>

<h2 id="final-thoughts">Final thoughts</h2>

<p>And that concludes our discussion of the 24 JEP’s that come with Java 24. But that’s not even all that’s new: <a href="https://jdk.java.net/24/release-notes">many other updates</a> were included in this release, including various performance, stability and security updates. So what are you waiting for? Time to take this brand-new Java release for a spin!</p>]]></content><author><name>Hanno Embregts</name></author><category term="java" /><summary type="html"><![CDATA[Java 24 rolls out today, and it brings a diverse set of features. For example, compact object headers bring better performance, and various security features have been added. Or how about the eagerly-awaited solution to virtual thread pinning? This post has all the info!]]></summary></entry><entry><title type="html">Java 23 Has Arrived, And It Brings a Truckload of Changes</title><link href="https://hanno.codes/2024/09/17/java-23-has-arrived/" rel="alternate" type="text/html" title="Java 23 Has Arrived, And It Brings a Truckload of Changes" /><published>2024-09-17T02:30:00+00:00</published><updated>2024-09-17T02:30:00+00:00</updated><id>https://hanno.codes/2024/09/17/java-23-has-arrived</id><content type="html" xml:base="https://hanno.codes/2024/09/17/java-23-has-arrived/"><![CDATA[<p>Java 23 has arrived! It’s been six months since Java 22 was released, so it’s time for a fresh truckload of changes. This post takes you on a tour of everything that is part of this release, giving you a brief introduction to each of them. Where applicable the differences with Java 22 are highlighted and a few typical use cases are provided, so that you’ll be more than ready to start using these features after reading this.</p>

<p><img src="/assets/images/blog/road-train.jpg" alt="Java 23 brings a truckload of features" /></p>
<blockquote>
  <p>Image from <a href="https://pxhere.com/en/photo/772190">PxHere</a></p>
</blockquote>

<h2 id="from-project-amber">From Project Amber</h2>

<p>Java 23 contains 4 features that originated from <a href="https://openjdk.org/projects/amber/">Project Amber</a>:</p>

<ul>
  <li>Primitive Types in Patterns, instanceof, and switch (Preview)</li>
  <li>Module Import Declarations (Preview)</li>
  <li>Implicitly Declared Classes and Instance Main Methods (Third Preview)</li>
  <li>Flexible Constructor Bodies (Second Preview)</li>
</ul>

<blockquote>
  <p>The goal of Project Amber is to explore and incubate smaller, productivity-oriented Java language features.</p>
</blockquote>

<h3 id="jep-455-primitive-types-in-patterns-instanceof-and-switch-preview">JEP 455: Primitive Types in Patterns, instanceof, and switch (Preview)</h3>

<p>Pattern matching has become more prominent in Java since Java 16, but its support for primitives was always limited to nested record patterns. This JEP proposes to support primitive types in all pattern contexts, and to extend <code class="language-plaintext highlighter-rouge">instanceof</code> and <code class="language-plaintext highlighter-rouge">switch</code> to work with all primitive types.</p>

<h4 id="pattern-matching-for-switch">Pattern Matching for Switch</h4>

<p><a href="https://openjdk.org/jeps/441">Pattern matching for switch</a> currently doesn’t support type patterns that specify a primitive type. This JEP proposes to add support for primitive type patterns in <code class="language-plaintext highlighter-rouge">switch</code>, allowing the following code example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">switch</span> <span class="o">(</span><span class="n">reverb</span><span class="o">.</span><span class="na">roomSize</span><span class="o">())</span> <span class="o">{</span>
    <span class="k">case</span> <span class="mi">1</span> <span class="o">-&gt;</span> <span class="s">"Toilet"</span><span class="o">;</span>
    <span class="k">case</span> <span class="mi">2</span> <span class="o">-&gt;</span> <span class="s">"Bedroom"</span><span class="o">;</span>
    <span class="k">case</span> <span class="mi">30</span> <span class="o">-&gt;</span> <span class="s">"Classroom"</span><span class="o">;</span>
    <span class="k">default</span> <span class="o">-&gt;</span> <span class="s">"Unsupported value: "</span> <span class="o">+</span> <span class="n">reverb</span><span class="o">.</span><span class="na">roomSize</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>

<p>…to be written as follows:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">switch</span> <span class="o">(</span><span class="n">reverb</span><span class="o">.</span><span class="na">roomSize</span><span class="o">())</span> <span class="o">{</span>
    <span class="k">case</span> <span class="mi">1</span> <span class="o">-&gt;</span> <span class="s">"Toilet"</span><span class="o">;</span>
    <span class="k">case</span> <span class="mi">2</span> <span class="o">-&gt;</span> <span class="s">"Bedroom"</span><span class="o">;</span>
    <span class="k">case</span> <span class="mi">30</span> <span class="o">-&gt;</span> <span class="s">"Classroom"</span><span class="o">;</span>
    <span class="k">case</span> <span class="kt">int</span> <span class="n">i</span> <span class="o">-&gt;</span> <span class="s">"Unsupported int value: "</span> <span class="o">+</span> <span class="n">i</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This also allows guards to inspect the matched value, like so:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">switch</span> <span class="o">(</span><span class="n">reverb</span><span class="o">.</span><span class="na">roomSize</span><span class="o">())</span> <span class="o">{</span>
    <span class="k">case</span> <span class="mi">1</span> <span class="o">-&gt;</span> <span class="s">"Toilet"</span><span class="o">;</span>
    <span class="k">case</span> <span class="mi">2</span> <span class="o">-&gt;</span> <span class="s">"Bedroom"</span><span class="o">;</span>
    <span class="k">case</span> <span class="mi">30</span> <span class="o">-&gt;</span> <span class="s">"Classroom"</span><span class="o">;</span>
    <span class="k">case</span> <span class="kt">int</span> <span class="n">i</span> <span class="n">when</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="mi">100</span> <span class="o">&amp;&amp;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">1000</span> <span class="o">-&gt;</span> <span class="s">"Cinema"</span><span class="o">;</span>
    <span class="k">case</span> <span class="kt">int</span> <span class="n">i</span> <span class="n">when</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="mi">5000</span> <span class="o">-&gt;</span> <span class="s">"Stadium"</span><span class="o">;</span>
    <span class="k">case</span> <span class="kt">int</span> <span class="n">i</span> <span class="o">-&gt;</span> <span class="s">"Unsupported int value: "</span> <span class="o">+</span> <span class="n">i</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<h4 id="record-patterns">Record Patterns</h4>

<p><a href="https://openjdk.org/jeps/440">Record patterns</a> currently have limited support for primitive types.
Recall that a record pattern decomposes a record into its individual components, but when one of them is a primitive type, the record pattern must be precise about its type. To illustrate this point, consider the following code example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">record</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">double</span> <span class="n">pitchInHz</span><span class="o">)</span> <span class="kd">implements</span> <span class="nc">Effect</span> <span class="o">{}</span>

<span class="kt">var</span> <span class="n">tuner</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Tuner</span><span class="o">(</span><span class="mi">440</span><span class="o">);</span> <span class="c1">// int argument is widened to double</span>

<span class="c1">// Attempt 1: record pattern match on int argument</span>
<span class="k">if</span> <span class="o">(</span><span class="n">tuner</span> <span class="k">instanceof</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">int</span> <span class="n">p</span><span class="o">))</span> <span class="o">{}</span> <span class="c1">// doesn't compile!</span>

<span class="c1">// Attempt 2: record pattern match on double argument</span>
<span class="k">if</span> <span class="o">(</span><span class="n">tuner</span> <span class="k">instanceof</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">double</span> <span class="n">p</span><span class="o">))</span> <span class="o">{</span>
    <span class="kt">int</span> <span class="n">pitch</span> <span class="o">=</span> <span class="n">p</span><span class="o">;</span> <span class="c1">// doesn't compile! needs a cast to int</span>
<span class="o">}</span>

<span class="c1">// Attempt 3: record pattern match on double argument, cast to int</span>
<span class="k">if</span> <span class="o">(</span><span class="n">tuner</span> <span class="k">instanceof</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">double</span> <span class="n">p</span><span class="o">))</span> <span class="o">{</span>
    <span class="kt">int</span> <span class="n">pitch</span> <span class="o">=</span> <span class="o">(</span><span class="kt">int</span><span class="o">)</span> <span class="n">p</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<p>To put it differently, the Java compiler widens the provided <code class="language-plaintext highlighter-rouge">int</code> to a double, but it doesn’t narrow it back to an <code class="language-plaintext highlighter-rouge">int</code>. This limitation exists because narrowing could lead to data loss: the value of the <code class="language-plaintext highlighter-rouge">double</code> at runtime might exceed the range of an <code class="language-plaintext highlighter-rouge">int</code> or have more precision than an <code class="language-plaintext highlighter-rouge">int</code> can accommodate. However, one significant advantage of pattern matching is its ability to automatically reject invalid values by not matching them at all. If the <code class="language-plaintext highlighter-rouge">double</code> component of a <code class="language-plaintext highlighter-rouge">Tuner</code> is either too large or too precise to safely convert back to an <code class="language-plaintext highlighter-rouge">int</code>, then <code class="language-plaintext highlighter-rouge">instanceof Tuner(int p)</code> would simply return <code class="language-plaintext highlighter-rouge">false</code>, allowing the program to manage the large <code class="language-plaintext highlighter-rouge">double</code> component in a different code branch.</p>

<p>This is analogous to how pattern matching currently behaves for reference type patterns. For example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">record</span> <span class="nf">SingleEffect</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">)</span> <span class="o">{}</span>
<span class="kt">var</span> <span class="n">singleEffect</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">SingleEffect</span><span class="o">(...);</span>

<span class="k">if</span> <span class="o">(</span><span class="n">singleEffect</span> <span class="k">instanceof</span> <span class="nf">SingleEffect</span><span class="o">(</span><span class="nc">Delay</span> <span class="n">d</span><span class="o">))</span> <span class="o">{</span>
    <span class="c1">// ...</span>
<span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">singleEffect</span> <span class="k">instanceof</span> <span class="nf">SingleEffect</span><span class="o">(</span><span class="nc">Reverb</span> <span class="n">r</span><span class="o">))</span> <span class="o">{</span>
    <span class="c1">// ...</span>
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
    <span class="c1">// ...</span>
<span class="o">}</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">instanceof</code> can be used here to try to match a <code class="language-plaintext highlighter-rouge">SingleEffect</code> with a <code class="language-plaintext highlighter-rouge">Delay</code> or a <code class="language-plaintext highlighter-rouge">Reverb</code> component; it automatically narrows if the pattern matches.</p>

<p>To summarize, this JEP proposes to make primitive type patterns work as smoothly as reference type patterns, allowing <code class="language-plaintext highlighter-rouge">Tuner(int p)</code> even if the corresponding record component is a numeric primitive type other than <code class="language-plaintext highlighter-rouge">int</code>.</p>

<h4 id="pattern-matching-for-instanceof">Pattern Matching for instanceof</h4>

<p><a href="https://openjdk.org/jeps/394">Pattern matching for instanceof</a> currently doesn’t support primitive type patterns, but this capability would perfectly align with the purpose of <code class="language-plaintext highlighter-rouge">instanceof</code>: to test whether a value can be converted safely to a given type. To convert primitives safely, Java developers currently have to deal with lossy casts and range checks to prevent loss of information:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">roomSize</span> <span class="o">=</span> <span class="n">reverb</span><span class="o">.</span><span class="na">roomSize</span><span class="o">();</span>

<span class="k">if</span> <span class="o">(</span><span class="n">roomSize</span> <span class="o">&gt;=</span> <span class="o">-</span><span class="mi">128</span> <span class="o">&amp;&amp;</span> <span class="n">roomSize</span> <span class="o">&lt;</span> <span class="mi">127</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">byte</span> <span class="n">r</span> <span class="o">=</span> <span class="o">(</span><span class="kt">byte</span><span class="o">)</span> <span class="n">roomSize</span><span class="o">;</span>
    <span class="c1">// now it's safe to use r</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This JEP proposes the possibility to replace these constructs with simple <code class="language-plaintext highlighter-rouge">instanceof</code> checks that operate on primitives. Let’s rewrite the code example to make use of this feature:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">roomSize</span> <span class="o">=</span> <span class="n">reverb</span><span class="o">.</span><span class="na">roomSize</span><span class="o">();</span>

<span class="k">if</span> <span class="o">(</span><span class="n">roomSize</span> <span class="k">instanceof</span> <span class="kt">byte</span> <span class="n">r</span><span class="o">)</span> <span class="o">{</span>
    <span class="c1">// now it's safe to use r</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The pattern <code class="language-plaintext highlighter-rouge">roomSize instanceof byte r</code> will match only if <code class="language-plaintext highlighter-rouge">roomSize</code> fits into a <code class="language-plaintext highlighter-rouge">byte</code>, eliminating the need for casts and range checks.</p>

<h4 id="primitive-types-in-instanceof">Primitive Types in instanceof</h4>

<p>The <code class="language-plaintext highlighter-rouge">instanceof</code> keyword used to take a reference type only, and since Java 16 it can also take a type pattern.
But it would make sense to have <code class="language-plaintext highlighter-rouge">instanceof</code> take a primitive type also.
In that case <code class="language-plaintext highlighter-rouge">instanceof</code> would check if the conversion is safe but would not actually perform it:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="o">(</span><span class="n">roomSize</span> <span class="k">instanceof</span> <span class="kt">byte</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// check if value of roomSize fits in a byte</span>
    <span class="o">...</span> <span class="o">(</span><span class="kt">byte</span><span class="o">)</span> <span class="n">roomSize</span> <span class="o">...</span> <span class="c1">// yes, it fits! but cast is required</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This JEP proposes to support this construct, which makes it easier to change the <code class="language-plaintext highlighter-rouge">instanceof</code> check to take a type pattern and vice versa.</p>

<h4 id="primitive-types-in-switch">Primitive Types in switch</h4>

<p>The <code class="language-plaintext highlighter-rouge">switch</code> statement/expression currently supports <code class="language-plaintext highlighter-rouge">byte</code>, <code class="language-plaintext highlighter-rouge">short</code>, <code class="language-plaintext highlighter-rouge">char</code>, and <code class="language-plaintext highlighter-rouge">int</code> values.
This JEP proposes to also add support for the other primitive types: <code class="language-plaintext highlighter-rouge">boolean</code>, <code class="language-plaintext highlighter-rouge">float</code>, <code class="language-plaintext highlighter-rouge">double</code> and <code class="language-plaintext highlighter-rouge">long</code>.
A <code class="language-plaintext highlighter-rouge">switch</code> on a <code class="language-plaintext highlighter-rouge">boolean</code> value can be a good alternative for the ternary operator (<code class="language-plaintext highlighter-rouge">?:</code>), because its branches can also hold statements instead of just expressions.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">guitaristResponse</span> <span class="o">=</span> <span class="k">switch</span> <span class="o">(</span><span class="n">guitar</span><span class="o">.</span><span class="na">isInTune</span><span class="o">())</span> <span class="o">{</span>
    <span class="k">case</span> <span class="kc">true</span> <span class="o">-&gt;</span> <span class="s">"Ready to play a song."</span><span class="o">;</span>
    <span class="k">case</span> <span class="kc">false</span> <span class="o">-&gt;</span> <span class="o">{</span>
        <span class="n">log</span><span class="o">.</span><span class="na">warn</span><span class="o">(</span><span class="s">"Guitar is out of tune!"</span><span class="o">);</span>
        <span class="n">yield</span> <span class="s">"Let's take five!"</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<h4 id="whats-different-from-java-22">What’s Different From Java 22?</h4>

<p>Java 22 didn’t support primitive types in patterns, instanceof and switch yet. Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/455">JEP 455</a>.</p>

<h3 id="jep-476-module-import-declarations-preview">JEP 476: Module Import Declarations (Preview)</h3>

<p>Many essential classes in the Java Class Library require imports to be usable.
In the following code, for example…</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">java.util.Map</span><span class="o">;</span>                   <span class="c1">// or import java.util.*;</span>
<span class="kn">import</span> <span class="nn">java.util.function.Function</span><span class="o">;</span>     <span class="c1">// or import java.util.function.*;</span>
<span class="kn">import</span> <span class="nn">java.util.stream.Collectors</span><span class="o">;</span>     <span class="c1">// or import java.util.stream.*;</span>
<span class="kn">import</span> <span class="nn">java.util.stream.Stream</span><span class="o">;</span>         <span class="c1">// </span>

<span class="nc">String</span><span class="o">[]</span> <span class="n">instruments</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">String</span><span class="o">[]</span> <span class="o">{</span> <span class="s">"violin"</span><span class="o">,</span> <span class="s">"piano"</span><span class="o">,</span> <span class="s">"marimba"</span> <span class="o">};</span>
<span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">String</span><span class="o">&gt;</span> <span class="n">m</span> <span class="o">=</span>
    <span class="nc">Stream</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="n">instruments</span><span class="o">)</span>
          <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toMap</span><span class="o">(</span><span class="n">s</span> <span class="o">-&gt;</span> <span class="n">s</span><span class="o">.</span><span class="na">toUpperCase</span><span class="o">().</span><span class="na">substring</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="mi">1</span><span class="o">),</span> <span class="nc">Function</span><span class="o">.</span><span class="na">identity</span><span class="o">()));</span>
</code></pre></div></div>

<p>…the imports take up just as much space as the code itself.</p>

<p>Whether that’s a bad thing or not depends on your import type preference.
In large, mature projects <a href="https://google.github.io/styleguide/javaguide.html#s3.3-import-statements">single-type imports</a> are preferred by many.
However, in early-stage situations (when trying out a new feature, or when you’re in <a href="https://openjdk.org/jeps/222">JShell</a>) a more convenient approach could come in handy.</p>

<h4 id="module-import-declarations">Module Import Declarations</h4>

<p>This JEP introduces <em>module import declarations</em>, and they have the form <code class="language-plaintext highlighter-rouge">import module M;</code>.
A module import declaration imports all of the public top-level classes and interfaces in the packages exported by the module <code class="language-plaintext highlighter-rouge">M</code> to the current module. Any indirect exports by the module <code class="language-plaintext highlighter-rouge">M</code> will also be made available by a module import declaration.</p>

<p>For example, if you write <code class="language-plaintext highlighter-rouge">import module java.sql</code>, it means your class will be able to read classes and interfaces from the packages <code class="language-plaintext highlighter-rouge">java.sql</code> and <code class="language-plaintext highlighter-rouge">javax.sql</code> (because they are exported by the module <a href="https://docs.oracle.com/en/java/javase/22/docs/api/java.sql/module-summary.html#packages-summary"><code class="language-plaintext highlighter-rouge">java.sql</code></a>). On top of that, because <code class="language-plaintext highlighter-rouge">java.sql</code> pulls in three other modules transitively, any exported packages from those modules will also be available.</p>

<h4 id="ambiguous-imports">Ambiguous Imports</h4>

<p>When you import a module, it brings in several packages, which means you might end up importing classes that have the same simple name from different packages. This creates ambiguity, leading to a compile-time error.</p>

<p>In this source file, the simple name <code class="language-plaintext highlighter-rouge">Date</code> is ambiguous:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">module</span> <span class="n">java</span><span class="o">.</span><span class="na">base</span><span class="o">;</span>      <span class="c1">// exports java.util, which has a public Date class</span>
<span class="kn">import</span> <span class="nn">module</span> <span class="n">java</span><span class="o">.</span><span class="na">sql</span><span class="o">;</span>       <span class="c1">// exports java.sql, which has a public Date class</span>

<span class="o">...</span>
<span class="nc">Date</span> <span class="n">d</span> <span class="o">=</span> <span class="o">...</span>                  <span class="c1">// Error - Ambiguous name!</span>
<span class="o">...</span>
</code></pre></div></div>

<p>Resolving ambiguities is straightforward: use a single-type-import declaration. For example, to resolve the ambiguous <code class="language-plaintext highlighter-rouge">Date</code> of the previous example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">module</span> <span class="n">java</span><span class="o">.</span><span class="na">base</span><span class="o">;</span>      <span class="c1">// exports java.util, which has a public Date class</span>
<span class="kn">import</span> <span class="nn">module</span> <span class="n">java</span><span class="o">.</span><span class="na">sql</span><span class="o">;</span>       <span class="c1">// exports java.sql, which has a public Date class</span>

<span class="kn">import</span> <span class="nn">java.sql.Date</span><span class="o">;</span>         <span class="c1">// resolve the ambiguity of the simple name Date</span>

<span class="o">...</span>
<span class="nc">Date</span> <span class="n">d</span> <span class="o">=</span> <span class="o">...</span>                  <span class="c1">// Ok! Date is resolved to java.sql.Date</span>
<span class="o">...</span>
</code></pre></div></div>

<h4 id="whats-different-from-java-22-1">What’s Different From Java 22?</h4>

<p>Up until Java 22, to import all public top-level classes and interfaces from a module, a wildcard-type import was required for each package in the module. In Java 23 the same behaviour can be achieved using a single module import declaration. Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-1">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/476">JEP 476</a>.</p>

<h3 id="jep-477-implicitly-declared-classes-and-instance-main-methods-third-preview">JEP 477: Implicitly Declared Classes and Instance Main Methods (Third Preview)</h3>

<p>Java’s take on the classic <a href="https://en.wikipedia.org/wiki/%22Hello,_World!%22_program">Hello, World!</a> program is notoriously verbose:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="o">{</span> 
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span> 
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello, World!"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>On top of that, it forces newcomers to grasp a few concepts that they certainly don’t need on their first day of Java programming:</p>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">public</code> access modifier and its role in encapsulating units of code, together with its counterparts <code class="language-plaintext highlighter-rouge">private</code>, <code class="language-plaintext highlighter-rouge">protected</code> and default;</li>
  <li>The <code class="language-plaintext highlighter-rouge">String[] args</code> parameter, that allows the operating system’s shell to pass arguments to the program;</li>
  <li>The <code class="language-plaintext highlighter-rouge">static</code> modifier and how it’s part of Java’s class-and-object model;</li>
  <li>How to import basic utility classes, to prevent the need for the mysterious <code class="language-plaintext highlighter-rouge">System.out.println</code> incantation.</li>
</ul>

<p>The motivation for this JEP is to help programmers that are new to Java by introducing concepts in the right order, starting with the more fundamental ones. This is done by hiding any unnecessary details until they are useful in larger programs.</p>

<h4 id="proposed-changes">Proposed Changes</h4>

<p>To achieve this, the JEP proposes the following changes:</p>

<ul>
  <li>change the launch protocol to allow <em>instance main methods</em>, which are not <code class="language-plaintext highlighter-rouge">static</code> and don’t need a <code class="language-plaintext highlighter-rouge">public</code> modifier, nor a <code class="language-plaintext highlighter-rouge">String[]</code> parameter;</li>
</ul>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="o">{</span> 
    <span class="kt">void</span> <span class="nf">main</span><span class="o">()</span> <span class="o">{</span> <span class="c1">// this is an instance main method</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello, World!"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<ul>
  <li>allow a compilation unit to implicitly declare a class:</li>
</ul>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">main</span><span class="o">()</span> <span class="o">{</span> <span class="c1">// this is an instance main method in an implicitly declared class</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello, World!"</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<ul>
  <li>in implicitly declared classes, automatically import useful methods for textual input and output, thereby avoiding the mysterious <code class="language-plaintext highlighter-rouge">System.out.println</code>:</li>
</ul>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">main</span><span class="o">()</span> <span class="o">{</span>
    <span class="n">println</span><span class="o">(</span><span class="s">"Hello, World!"</span><span class="o">);</span> <span class="c1">// this method is automatically imported</span>
<span class="o">}</span>
</code></pre></div></div>

<h4 id="a-flexible-launch-protocol">A Flexible Launch Protocol</h4>

<p>Java 23 enhances the launch protocol to offer more flexibility in declaring a program’s entry point. The <code class="language-plaintext highlighter-rouge">main</code> method of a launched class can now have <code class="language-plaintext highlighter-rouge">public</code>, <code class="language-plaintext highlighter-rouge">protected</code> or default access. Other enhancements of the launch protocol include:</p>

<ul>
  <li>If the launched class contains a main method with a <code class="language-plaintext highlighter-rouge">String[]</code> parameter, then choose that method.</li>
  <li>Otherwise, if the class contains a main method with no parameters, then choose that method.</li>
  <li>In either case, if the chosen method is <code class="language-plaintext highlighter-rouge">static</code>, then simply invoke it.</li>
  <li>Otherwise, the chosen method is an instance method and the launched class must have a zero-parameter, non-private constructor. Invoke that constructor and then invoke the <code class="language-plaintext highlighter-rouge">main</code> method of the resulting object. If there is no such constructor, then report an error and terminate.</li>
  <li>If there is no suitable <code class="language-plaintext highlighter-rouge">main</code> method, then report an error and terminate.</li>
</ul>

<h4 id="implicitly-declared-classes">Implicitly Declared Classes</h4>

<p>With the introduction of implicitly declared classes, the Java compiler will consider a method that is not enclosed in a class declaration, as well as any unenclosed fields and any classes declared in the file, to be members of an implicitly declared top-level class. 
Such a class always belongs to the unnamed package, is <code class="language-plaintext highlighter-rouge">final</code>, and can’t implement interfaces or extend classes except <code class="language-plaintext highlighter-rouge">Object</code>. You can’t reference it by name or use method references for its static methods, but you can use <code class="language-plaintext highlighter-rouge">this</code> and make method references to its instance methods. Implicitly declared classes can’t be instantiated or referenced by name in code. They’re mainly used as program entry points and must have a <code class="language-plaintext highlighter-rouge">main</code> method, enforced by the Java compiler.</p>

<h4 id="interacting-with-the-console">Interacting with the Console</h4>

<p>Many beginner programs need to interact with the console, for example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">java.io.BufferedReader</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.IOException</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.InputStreamReader</span><span class="o">;</span>

<span class="kd">class</span> <span class="nc">Main</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">...</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Please enter your name:"</span><span class="o">);</span>
        <span class="nc">String</span> <span class="n">name</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
        <span class="k">try</span> <span class="o">{</span>
            <span class="nc">BufferedReader</span> <span class="n">reader</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BufferedReader</span><span class="o">(</span><span class="k">new</span> <span class="nc">InputStreamReader</span><span class="o">(</span><span class="nc">System</span><span class="o">.</span><span class="na">in</span><span class="o">));</span>
            <span class="n">name</span> <span class="o">=</span> <span class="n">reader</span><span class="o">.</span><span class="na">readLine</span><span class="o">();</span>
        <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">ioe</span><span class="o">)</span> <span class="o">{</span>
            <span class="n">ioe</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
        <span class="o">}</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello, "</span> <span class="o">+</span> <span class="n">name</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The code may seem familiar to experienced developers, but beginners often find it confusing due to new concepts like <code class="language-plaintext highlighter-rouge">import</code>, <code class="language-plaintext highlighter-rouge">try</code>, <code class="language-plaintext highlighter-rouge">catch</code>, <code class="language-plaintext highlighter-rouge">BufferedReader</code>, <code class="language-plaintext highlighter-rouge">InputStreamReader</code> and <code class="language-plaintext highlighter-rouge">IOException</code>. While there are other approaches, none are significantly better for those just starting out.</p>

<p>To make interacting with the console easier for beginners, implicit classes now automatically import all static methods from the newly added class <a href="https://cr.openjdk.org/~prappo/8305457/java.base/java/io/IO.html"><code class="language-plaintext highlighter-rouge">java.io.IO</code></a>:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">public static void println(Object obj);</code></li>
  <li><code class="language-plaintext highlighter-rouge">public static void print(Object obj);</code></li>
  <li><code class="language-plaintext highlighter-rouge">public static String readln(String prompt);</code></li>
</ul>

<p>Combined with the other features from this JEP, the code above can now be simplified to:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">main</span><span class="o">()</span> <span class="o">{</span>
    <span class="nc">String</span> <span class="n">name</span> <span class="o">=</span> <span class="n">readln</span><span class="o">(</span><span class="s">"Please enter your name:"</span><span class="o">);</span>
    <span class="n">print</span><span class="o">(</span><span class="s">"Hello, "</span><span class="o">);</span>
    <span class="n">println</span><span class="o">(</span><span class="n">name</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<h4 id="automatic-import-of-the-javabase-module">Automatic Import of the <code class="language-plaintext highlighter-rouge">java.base</code> Module</h4>

<p>To make writing small programs even easier, all public top-level classes and interfaces from the <code class="language-plaintext highlighter-rouge">java.base</code> module are now automatically available in every implicit class, as if they were imported. 
This means that popular APIs from packages like <code class="language-plaintext highlighter-rouge">java.io</code>, <code class="language-plaintext highlighter-rouge">java.math</code>, and <code class="language-plaintext highlighter-rouge">java.util</code> can be used right away, eliminating the need for explicit import statements that might confuse beginners.</p>

<blockquote>
  <p>This implicit behaviour can also be made explicit to make it work in any other class, by using a <a href="#jep-476-module-import-declarations-preview">module import declaration</a> like <code class="language-plaintext highlighter-rouge">import module java.base</code>, which can be helpful when converting an implicit class to a top-level class.</p>
</blockquote>

<h4 id="whats-different-from-java-22-2">What’s Different From Java 22?</h4>

<p>Java 23 contains the following changes compared to Java 22:</p>

<ul>
  <li>Implicitly declared classes automatically import three static methods for simple textual I/O with the console. These methods are declared in the new top-level class <a href="https://cr.openjdk.org/~prappo/8305457/java.base/java/io/IO.html"><code class="language-plaintext highlighter-rouge">java.io.IO</code></a>.</li>
  <li>Implicitly declared classes automatically import, on demand, all of the public top-level classes and interfaces of the packages exported by the <code class="language-plaintext highlighter-rouge">java.base</code> module.</li>
</ul>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-2">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/477">JEP 477</a>.</p>

<h3 id="jep-482-flexible-constructor-bodies-second-preview">JEP 482: Flexible Constructor Bodies (Second Preview)</h3>

<p>Suppose we have a superclass <code class="language-plaintext highlighter-rouge">Orchestra</code> and a subclass <code class="language-plaintext highlighter-rouge">StringQuartet</code>. The constructors of these classes must work together to ensure a valid instance. The <code class="language-plaintext highlighter-rouge">StringQuartet</code> constructor is responsible for any <code class="language-plaintext highlighter-rouge">StringQuartet</code>-specific fields, while the <code class="language-plaintext highlighter-rouge">Orchestra</code> constructor is responsible for fields declared in the <code class="language-plaintext highlighter-rouge">Orchestra</code> class. Since code in the <code class="language-plaintext highlighter-rouge">StringQuartet</code> constructor might refer to fields initialized by the <code class="language-plaintext highlighter-rouge">Orchestra</code> constructor, the latter must run first.</p>

<p>This example illustrates that constructors should run from top to bottom. This also means that a superclass constructor must finish initializing its fields before a subclass constructor starts, ensuring proper object state initialization and preventing access to uninitialized fields. Java enforces this by requiring explicit constructor calls (like <code class="language-plaintext highlighter-rouge">super(...)</code> or <code class="language-plaintext highlighter-rouge">this(...)</code>) to be the first statement in a constructor body, and constructor arguments cannot access the current object. While these rules ensure that constructors behave predictably, they may restrict the use of common programming patterns in constructor methods. The following code example illustrates this point:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">StringQuartet</span> <span class="kd">extends</span> <span class="nc">Orchestra</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="nf">StringQuartet</span><span class="o">(</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Instrument</span><span class="o">&gt;</span> <span class="n">instruments</span><span class="o">)</span> <span class="o">{</span>
        <span class="kd">super</span><span class="o">(</span><span class="n">instruments</span><span class="o">);</span> <span class="c1">// Potentially unnecessary work!</span>

        <span class="k">if</span> <span class="o">(</span><span class="n">instruments</span><span class="o">.</span><span class="na">size</span><span class="o">()</span> <span class="o">!=</span> <span class="mi">4</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalArgumentException</span><span class="o">(</span><span class="s">"Not a quartet!"</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>It would be better to let the constructor fail fast, by validating its arguments before the <code class="language-plaintext highlighter-rouge">super(...)</code> constructor is called.
Pre-Java 22, we could only achieve this by introducing a <code class="language-plaintext highlighter-rouge">static</code> method that acts upon the value passed to the super constructor.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">StringQuartet</span> <span class="kd">extends</span> <span class="nc">Orchestra</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="nf">StringQuartet</span><span class="o">(</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Instrument</span><span class="o">&gt;</span> <span class="n">instruments</span><span class="o">)</span> <span class="o">{</span>
        <span class="kd">super</span><span class="o">(</span><span class="n">validate</span><span class="o">(</span><span class="n">instruments</span><span class="o">));</span>
    <span class="o">}</span>

    <span class="kd">private</span> <span class="kd">static</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Instrument</span><span class="o">&gt;</span> <span class="nf">validate</span><span class="o">(</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Instrument</span><span class="o">&gt;</span> <span class="n">instruments</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">instruments</span><span class="o">.</span><span class="na">size</span><span class="o">()</span> <span class="o">!=</span> <span class="mi">4</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalArgumentException</span><span class="o">(</span><span class="s">"Not a quartet!"</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>But a far more readable way to write the same would be:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">StringQuartet</span> <span class="kd">extends</span> <span class="nc">Orchestra</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="nf">StringQuartet</span><span class="o">(</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Instrument</span><span class="o">&gt;</span> <span class="n">instruments</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">instruments</span><span class="o">.</span><span class="na">size</span><span class="o">()</span> <span class="o">!=</span> <span class="mi">4</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalArgumentException</span><span class="o">(</span><span class="s">"Not a quartet!"</span><span class="o">);</span>
        <span class="o">}</span>

        <span class="kd">super</span><span class="o">(</span><span class="n">instruments</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This approach will be possible in Java 23, due to the introduction of <em>early construction contexts</em>.
Java used to treat the arguments to an explicit constructor invocation to be in a <em>static context</em>, as if they were in a static method. But this restriction is a bit stronger than necessary, which is why Java 23 introduces the aforementioned <em>early construction contexts</em>; a strictly weaker concept. It covers both the arguments to an explicit constructor invocation and any statements that occur before it. Code in an early construction context must not use the instance under construction, except to initialize fields that do not have their own initializers.</p>

<h4 id="whats-different-from-java-22-3">What’s Different From Java 22?</h4>

<ul>
  <li>The feature was renamed: in Java 22 it was known as “Statements before super(…)”;</li>
  <li>A constructor body is now allowed to initialize fields in the same class before explicitly invoking a constructor. This possibility prevents any superclass constructor from seeing the default value of a subclass field (like <code class="language-plaintext highlighter-rouge">0</code>, <code class="language-plaintext highlighter-rouge">false</code> or <code class="language-plaintext highlighter-rouge">null</code>).</li>
</ul>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-3">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/482">JEP 482</a>.</p>

<h3 id="what-happened-to-string-templates">What Happened to String Templates?</h3>

<p>Java 22 had a feature called <a href="https://hanno.codes/2024/03/19/java-22-is-here/#jep-459-string-templates-second-preview">string templates</a>, which was in second preview back then. 
However, the feature is <em>not</em> included in Java 23, which might be surprising, but at the same time it’s a valid possibility.
We have always known that <a href="https://openjdk.org/jeps/12">preview features are impermanent</a>, and might even be removed instead of promoted to ‘final’ status.</p>

<p>So what happened? Well, in short: the effort did not meet the needs of the developers.
Like any preview feature, feedback was received from the developer community, and quite a few issues were raised.
Some remarks were about syntax, and others were about nested templates.
But the most relevant feedback was about the co-dependence of <em>string templates</em> and <em>template processors</em>.
To make the feature perform better than <code class="language-plaintext highlighter-rouge">String.format(...)</code>, it was crucial that the template processor would appear close to the string template it had to process, which is why the special syntax <code class="language-plaintext highlighter-rouge">PROCESSOR."template"</code> was introduced.
Based on the feedback, on the <a href="https://mail.openjdk.org/pipermail/amber-spec-observers/2024-March/thread.html#4230">Project Amber mailing list</a>  a discovery was made: the template and the code processing it didn’t <em>have</em> to appear side by side to achieve the performance boost. This meant that the special syntax could also potentially be dropped.
This realization ultimately sent the feature back to the drawing board! 
While the new direction was taking shape, the Java 23 deadline was fast approaching and the choice was made to drop the feature entirely, instead of repreviewing it unchanged while everyone knew the design would change drastically in the future.</p>

<h4 id="what-happens-next">What Happens Next?</h4>

<p>So, what happens next? Well, a new JEP will probably appear in the future, but it might take a while, as much of the initial design has to be reconsidered.
But based on the above template processors probably won’t have a prominent place.
And string templates will probably become a new kind of literal (similar to String literals), because there’s no need for them to be tied to their template processor any more.
There’s no way for us to know exactly when a new proposal will be ready, so we’ll just have to wait and see.
And in the meantime, if you’re interested, <a href="https://inside.java/2024/06/20/newscast-71">this excellent video</a> by Nicolai Parlog has a few more interesting details to keep you occupied.</p>

<h2 id="from-project-loom">From Project Loom</h2>

<p>Java 23 contains 2 features that originated from <a href="http://openjdk.java.net/projects/loom/">Project Loom</a>:</p>

<ul>
  <li>Structured Concurrency (Third Preview)</li>
  <li>Scoped Values (Third Preview)</li>
</ul>

<blockquote>
  <p>Project Loom strives to simplify maintaining concurrent applications in Java by introducing <em>virtual threads</em> and an API for <em>structured concurrency</em>, among other things.</p>
</blockquote>

<h3 id="jep-480-structured-concurrency-third-preview">JEP 480: Structured Concurrency (Third Preview)</h3>

<p>Java’s take on concurrency has always been <em>unstructured</em>, meaning that tasks run independently of each other. There’s no hierarchy, scope, or other structure involved, which means errors or cancellation intent is hard to communicate.
To illustrate this, let’s look at a code example that takes place in a restaurant:</p>

<blockquote>
  <p>The code examples that illustrate Structured Concurrency were taken from my conference talk <a href="https://hanno.codes/talks/#javas-concurrency-journey-continues">“Java’s Concurrency Journey Continues! Exploring Structured Concurrency and Scoped Values”</a>.</p>
</blockquote>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">MultiWaiterRestaurant</span> <span class="kd">implements</span> <span class="nc">Restaurant</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">MultiCourseMeal</span> <span class="nf">announceMenu</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">ExecutionException</span><span class="o">,</span> <span class="nc">InterruptedException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">grover</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Grover"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">rosita</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Rosita"</span><span class="o">);</span>

        <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">executor</span> <span class="o">=</span> <span class="nc">Executors</span><span class="o">.</span><span class="na">newVirtualThreadPerTaskExecutor</span><span class="o">())</span> <span class="o">{</span>
            <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">starter</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">grover</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">STARTER</span><span class="o">));</span>
            <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">main</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">MAIN</span><span class="o">));</span>
            <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">dessert</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">rosita</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">DESSERT</span><span class="o">));</span>

            <span class="k">return</span> <span class="k">new</span> <span class="nf">MultiCourseMeal</span><span class="o">(</span><span class="n">starter</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">main</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">dessert</span><span class="o">.</span><span class="na">get</span><span class="o">());</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Note that the <code class="language-plaintext highlighter-rouge">announceCourse(..)</code> method in the <code class="language-plaintext highlighter-rouge">Waiter</code> class sometimes fails with an <code class="language-plaintext highlighter-rouge">OutOfStockException</code>, because one of the ingredients for the course might not be in stock. This can lead to some problems:</p>

<ul>
  <li>If <code class="language-plaintext highlighter-rouge">zoe.announceCourse(CourseType.MAIN)</code> takes a long time to execute but <code class="language-plaintext highlighter-rouge">grover.announceCourse(CourseType.STARTER)</code> fails in the meantime, the <code class="language-plaintext highlighter-rouge">announceMenu(..)</code> method will unnecessarily wait for the main course announcement by blocking on <code class="language-plaintext highlighter-rouge">main.get()</code>, instead of cancelling it (which would be the sensible thing to do).</li>
  <li>If an exception happens in <code class="language-plaintext highlighter-rouge">zoe.announceCourse(CourseType.MAIN)</code>, <code class="language-plaintext highlighter-rouge">main.get()</code> will throw it, but <code class="language-plaintext highlighter-rouge">grover.announceCourse(CourseType.STARTER)</code> will continue to run in its own thread, resulting in thread leakage.</li>
  <li>If the thread executing <code class="language-plaintext highlighter-rouge">announceMenu(..)</code> is interrupted, the interruption will not propagate to the subtasks: all threads that run an <code class="language-plaintext highlighter-rouge">announceCourse(..)</code> invocation will leak, continuing to run even after <code class="language-plaintext highlighter-rouge">announceMenu()</code> has failed.</li>
</ul>

<p>Ultimately the problem here is that our program is logically structured with task-subtask relationships, but these relationships exist only in the mind of the developer. We might all prefer structured code that reads like a sequential story, but this example simply doesn’t meet that criterion.</p>

<p>In contrast, the execution of single-threaded code <em>always</em> enforces a hierarchy of tasks and subtasks, as shown by the single-threaded version of our restaurant example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">SingleWaiterRestaurant</span> <span class="kd">implements</span> <span class="nc">Restaurant</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">MultiCourseMeal</span> <span class="nf">announceMenu</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">OutOfStockException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">elmo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Elmo"</span><span class="o">);</span>

        <span class="nc">Course</span> <span class="n">starter</span> <span class="o">=</span> <span class="n">elmo</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">STARTER</span><span class="o">);</span>
        <span class="nc">Course</span> <span class="n">main</span> <span class="o">=</span> <span class="n">elmo</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">MAIN</span><span class="o">);</span>
        <span class="nc">Course</span> <span class="n">dessert</span> <span class="o">=</span> <span class="n">elmo</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">DESSERT</span><span class="o">);</span>

        <span class="k">return</span> <span class="k">new</span> <span class="nf">MultiCourseMeal</span><span class="o">(</span><span class="n">starter</span><span class="o">,</span> <span class="n">main</span><span class="o">,</span> <span class="n">dessert</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here, we don’t have <em>any</em> of the problems we had before.
Our waiter Elmo will announce the courses in exactly the right order, and if one subtask fails the remaining one(s) won’t even be started.
And because all work runs in the same thread, there is no risk of thread leakage.</p>

<p>It became apparent from these examples that concurrent programming would be a lot easier and more intuitive if enforcing the hierarchy of tasks and subtasks was possible, just like with single-threaded code.</p>

<h4 id="introducing-structured-concurrency">Introducing Structured Concurrency</h4>

<p>In a structured concurrency approach, threads have a clear hierarchy, their own scope, and clear entry and exit points. Structured concurrency arranges threads hierarchically, akin to function calls, forming a tree with parent-child relationships. Execution scopes persist until all child threads complete, matching code structure.</p>

<h4 id="shutdown-on-failure">Shutdown on Failure</h4>

<p>Let’s now take a look at a structured, concurrent version of our example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">StructuredConcurrencyRestaurant</span> <span class="kd">implements</span> <span class="nc">Restaurant</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">MultiCourseMeal</span> <span class="nf">announceMenu</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">ExecutionException</span><span class="o">,</span> <span class="nc">InterruptedException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">grover</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Grover"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">rosita</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Rosita"</span><span class="o">);</span>

        <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">scope</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StructuredTaskScope</span><span class="o">.</span><span class="na">ShutdownOnFailure</span><span class="o">())</span> <span class="o">{</span>
            <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">starter</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">grover</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">STARTER</span><span class="o">));</span>
            <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">main</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">MAIN</span><span class="o">));</span>
            <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">dessert</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">rosita</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">DESSERT</span><span class="o">));</span>

            <span class="n">scope</span><span class="o">.</span><span class="na">join</span><span class="o">();</span> <span class="c1">// 1</span>
            <span class="n">scope</span><span class="o">.</span><span class="na">throwIfFailed</span><span class="o">();</span> <span class="c1">// 2</span>

            <span class="k">return</span> <span class="k">new</span> <span class="nf">MultiCourseMeal</span><span class="o">(</span><span class="n">starter</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">main</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">dessert</span><span class="o">.</span><span class="na">get</span><span class="o">());</span> <span class="c1">// 3</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>The scope’s purpose is to keep the threads together.
At <code class="language-plaintext highlighter-rouge">1</code>, we wait (<code class="language-plaintext highlighter-rouge">join</code>) until <em>all</em> threads are done with their work. 
If one of the threads is interrupted, an <code class="language-plaintext highlighter-rouge">InterruptedException</code> is thrown here. 
At <code class="language-plaintext highlighter-rouge">2</code>, an <code class="language-plaintext highlighter-rouge">ExecutionException</code> is thrown if an exception occurs in one of the threads. 
Once we reach <code class="language-plaintext highlighter-rouge">3</code>, we can be sure everything has gone well, and we can retrieve and process the results.</p>

<p>Actually, the main difference with the code we had before is the fact that we create threads (<code class="language-plaintext highlighter-rouge">fork</code>) within a new <code class="language-plaintext highlighter-rouge">scope</code>. 
Now we can be certain that the lifetimes of the three threads are confined to this scope, which coincides with the body of the try-with-resources statement.</p>

<p>Furthermore, we’ve gained <em>short-circuiting behaviour</em>. 
When one of the <code class="language-plaintext highlighter-rouge">announceCourse(..)</code> subtasks fails, the others are cancelled if they didn’t complete yet.
This behaviour is managed by the <code class="language-plaintext highlighter-rouge">ShutdownOnFailure</code> policy.
We’ve also gained <em>cancellation propagation</em>.
When the thread that runs <code class="language-plaintext highlighter-rouge">announceMenu()</code> is interrupted before or during the call to <code class="language-plaintext highlighter-rouge">scope.join()</code>, all subtasks are cancelled automatically when the thread exits the scope.</p>

<h4 id="shutdown-on-success">Shutdown on Success</h4>

<p>A shutdown-on-failure policy cancels tasks if one of them fails, while a <em>shutdown-on-success</em> policy cancels tasks if one succeeds. The latter is useful to prevent unnecessary work once a successful result is obtained.</p>

<p>Let’s see what a shutdown-on-success implementation would look like:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="n">record</span> <span class="nf">DrinkOrder</span><span class="o">(</span><span class="nc">Guest</span> <span class="n">guest</span><span class="o">,</span> <span class="nc">Drink</span> <span class="n">drink</span><span class="o">)</span> <span class="o">{}</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">StructuredConcurrencyBar</span> <span class="kd">implements</span> <span class="nc">Bar</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">DrinkOrder</span> <span class="nf">determineDrinkOrder</span><span class="o">(</span><span class="nc">Guest</span> <span class="n">guest</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">InterruptedException</span><span class="o">,</span> <span class="nc">ExecutionException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">elmo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Elmo"</span><span class="o">);</span>

        <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">scope</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StructuredTaskScope</span><span class="o">.</span><span class="na">ShutdownOnSuccess</span><span class="o">&lt;</span><span class="nc">DrinkOrder</span><span class="o">&gt;())</span> <span class="o">{</span>
            <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">getDrinkOrder</span><span class="o">(</span><span class="n">guest</span><span class="o">,</span> <span class="no">BEER</span><span class="o">,</span> <span class="no">WINE</span><span class="o">,</span> <span class="no">JUICE</span><span class="o">));</span>
            <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">elmo</span><span class="o">.</span><span class="na">getDrinkOrder</span><span class="o">(</span><span class="n">guest</span><span class="o">,</span> <span class="no">COFFEE</span><span class="o">,</span> <span class="no">TEA</span><span class="o">,</span> <span class="no">COCKTAIL</span><span class="o">,</span> <span class="no">DISTILLED</span><span class="o">));</span>

            <span class="k">return</span> <span class="n">scope</span><span class="o">.</span><span class="na">join</span><span class="o">().</span><span class="na">result</span><span class="o">();</span> <span class="c1">// 1</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>In this example the waiter is responsible for getting a valid <code class="language-plaintext highlighter-rouge">DrinkOrder</code> object based on guest preference and the drinks supply at the bar.
In the method <code class="language-plaintext highlighter-rouge">Waiter.getDrinkOrder(Guest guest, DrinkCategory... categories)</code>, the waiter starts to list all available drinks in the drink categories that were passed to the method.
Once a guest hears something they like, they respond and the waiter creates a drink order. When this happens, the <code class="language-plaintext highlighter-rouge">getDrinkOrder(..)</code> method returns a <code class="language-plaintext highlighter-rouge">DrinkOrder</code> object and the scope will shut down. 
This means that any unfinished subtasks (such as the one in which Elmo is still listing different kinds of tea) will be cancelled.
The <code class="language-plaintext highlighter-rouge">result()</code> method at <code class="language-plaintext highlighter-rouge">1</code> will either return a valid <code class="language-plaintext highlighter-rouge">DrinkOrder</code> object, or throw an <code class="language-plaintext highlighter-rouge">ExecutionException</code> if one of the subtasks has failed.</p>

<h4 id="custom-shutdown-policies">Custom Shutdown Policies</h4>

<p>Two shutdown policies are provided out-of-the-box, but it’s also possible to create your own by extending the class <code class="language-plaintext highlighter-rouge">StructuredTaskScope</code> and its protected <code class="language-plaintext highlighter-rouge">handleComplete(..)</code> method.
That will allow you to have full control over when the scope will shut down and what results will be collected.</p>

<h4 id="whats-different-from-java-22-4">What’s Different From Java 22?</h4>

<p>Compared to the preview version of this feature in Java 22, nothing was changed or added. JEP 480 simply exists to gather more feedback from users. Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-4">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/480">JEP 480</a>.</p>

<h3 id="jep-481-scoped-values-third-preview">JEP 481: Scoped Values (Third Preview)</h3>

<p><em>Scoped values</em> 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.</p>

<blockquote>
  <p>The code examples that illustrate Scoped Values were taken from my conference talk <a href="https://hanno.codes/talks/#javas-concurrency-journey-continues">“Java’s Concurrency Journey Continues! Exploring Structured Concurrency and Scoped Values”</a>.</p>
</blockquote>

<h4 id="threadlocal">ThreadLocal</h4>

<p>Since Java 1.2 we can make use of <code class="language-plaintext highlighter-rouge">ThreadLocal</code> variables, which confine a certain value to the thread that created it. Back then this was a simple way to achieve thread-safety, <a href="https://stackoverflow.com/a/817926">in some cases</a>.</p>

<p>But thread-local variables also come with a few caveats. Every thread-local variable is mutable, making it hard to discern where shared state is updated and in what order. There’s also the risk of memory leaks, because unless you call <code class="language-plaintext highlighter-rouge">remove()</code> on the <code class="language-plaintext highlighter-rouge">ThreadLocal</code> the data is retained until it is garbage collected (which is only after the thread terminates). And finally, thread-local variables of a parent thread can be inherited by child threads, meaning that the child thread has to allocate storage for every thread-local variable previously written in the parent thread.</p>

<p>These drawbacks become more apparent now that virtual threads have been introduced, because millions of them could be active at the same time - each with their own thread-local variables - resulting in a significant memory footprint.</p>

<h4 id="scoped-values">Scoped Values</h4>

<p>Like a thread-local variable, a scoped value has multiple incarnations, one per thread. Unlike a thread-local variable, a scoped value is written once and is then immutable. It’s available only for a bounded period during execution of the thread.</p>

<p>To demonstrate this feature, we’ve added a scoped value to the <code class="language-plaintext highlighter-rouge">StructuredConcurrencyBar</code> class that you’re already familiar with:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">StructuredConcurrencyBar</span> <span class="kd">implements</span> <span class="nc">Bar</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="nc">ScopedValue</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">drinkOrderId</span> <span class="o">=</span> <span class="nc">ScopedValue</span><span class="o">.</span><span class="na">newInstance</span><span class="o">();</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">DrinkOrder</span> <span class="nf">determineDrinkOrder</span><span class="o">(</span><span class="nc">Guest</span> <span class="n">guest</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">elmo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Elmo"</span><span class="o">);</span>

        <span class="k">return</span> <span class="nc">ScopedValue</span><span class="o">.</span><span class="na">where</span><span class="o">(</span><span class="n">drinkOrderId</span><span class="o">,</span> <span class="mi">1</span><span class="o">)</span>
                <span class="o">.</span><span class="na">call</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="o">{</span>
                    <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">scope</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StructuredTaskScope</span><span class="o">.</span><span class="na">ShutdownOnSuccess</span><span class="o">&lt;</span><span class="nc">DrinkOrder</span><span class="o">&gt;())</span> <span class="o">{</span>
                        <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">getDrinkOrder</span><span class="o">(</span><span class="n">guest</span><span class="o">,</span> <span class="no">BEER</span><span class="o">,</span> <span class="no">WINE</span><span class="o">,</span> <span class="no">JUICE</span><span class="o">));</span>
                        <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">elmo</span><span class="o">.</span><span class="na">getDrinkOrder</span><span class="o">(</span><span class="n">guest</span><span class="o">,</span> <span class="no">COFFEE</span><span class="o">,</span> <span class="no">TEA</span><span class="o">,</span> <span class="no">COCKTAIL</span><span class="o">,</span> <span class="no">DISTILLED</span><span class="o">));</span>

                        <span class="k">return</span> <span class="n">scope</span><span class="o">.</span><span class="na">join</span><span class="o">().</span><span class="na">result</span><span class="o">();</span>
                    <span class="o">}</span>
                <span class="o">});</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>We see that <code class="language-plaintext highlighter-rouge">ScopedValue.where(...)</code> is called, presenting a scoped value and the object to which it is to be bound. The invocation of <code class="language-plaintext highlighter-rouge">call(...)</code> binds the scoped value, providing an incarnation that is specific to the current thread, and then executes the lambda expression passed as argument. During the lifetime of <code class="language-plaintext highlighter-rouge">call(...)</code>, the lambda expression - and any method called (in)directly from it - can read the scoped value via the value’s <code class="language-plaintext highlighter-rouge">get()</code> method. After the <code class="language-plaintext highlighter-rouge">call(...)</code> method finishes, the binding is destroyed.</p>

<h4 id="typical-use-cases">Typical Use Cases</h4>

<p>Scoped values will be useful in all places where currently thread-local variables are used for the purpose of one-way transmission of unchanging data.</p>

<h4 id="whats-different-from-java-22-5">What’s Different From Java 22?</h4>

<p>The method <code class="language-plaintext highlighter-rouge">ScopedValue.callWhere(key, value, operation)</code> (which is a shorter way to write <code class="language-plaintext highlighter-rouge">ScopedValue.where(key, value).call(operation);</code>) can now throw a checked exception of a generic type. This means that you’re now able to catch that exception like this:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="k">try</span> <span class="o">{</span>
        <span class="kt">var</span> <span class="n">result</span> <span class="o">=</span> <span class="nc">ScopedValue</span><span class="o">.</span><span class="na">callWhere</span><span class="o">(</span><span class="no">X</span><span class="o">,</span> <span class="s">"hello"</span><span class="o">,</span> <span class="o">()</span> <span class="o">-&gt;</span> <span class="n">bar</span><span class="o">());</span>
    <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">handleFailure</span><span class="o">(</span><span class="n">e</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="c1">// ...</span>
</code></pre></div></div>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-5">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/481">JEP 481</a>.</p>

<h2 id="hotspot">HotSpot</h2>

<p>Java 23 introduces a single change to <a href="https://openjdk.org/groups/hotspot/">HotSpot</a>:</p>

<ul>
  <li>ZGC: Generational Mode by Default</li>
</ul>

<blockquote>
  <p>The HotSpot JVM is the runtime engine that is developed by Oracle. It translates Java bytecode into machine code for the host operating system’s processor architecture.</p>
</blockquote>

<h3 id="jep-474-zgc-generational-mode-by-default">JEP 474: ZGC: Generational Mode by Default</h3>

<p>The Z Garbage Collector (ZGC) is a scalable, low-latency garbage collector. It has been <a href="https://openjdk.org/jeps/377">available for production use since Java 15</a> and has been designed to keep pause times consistent and short, even for very large heaps. It uses techniques like region-based memory management and compaction to achieve this.</p>

<p>Java 21 introduced <a href="https://openjdk.org/jeps/439">an extension to ZGC</a> that maintains separate <em>generations</em> for young and old objects, allowing ZGC to collect young objects (which tend to die young) more frequently. This will result in a significant performance gain for applications running with generational ZGC, without sacrificing any of the valuable properties that the Z garbage collector is already known for.</p>

<p>In Java 21, a command-line option was required to enable generational mode. Java 23 makes generational mode the default mode for ZGC, whereas non-generational mode has been deprecated. It will probably be removed in a future Java version.</p>

<h4 id="whats-different-from-java-22-6">What’s Different From Java 22?</h4>

<p>To run your workload with Generational ZGC in Java 22, the following configuration was needed:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:+UseZGC <span class="nt">-XX</span>:+ZGenerational ...
</code></pre></div></div>

<p>In Java 23, this command-line option is no longer needed, it will use generational mode by default:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:+UseZGC ...
</code></pre></div></div>

<p>When you <em>do</em> still include it, a warning will be issued that the <code class="language-plaintext highlighter-rouge">ZGenerational</code> option is deprecated.</p>

<p>To revert back to non-generational ZGC, you would need to run:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-XX</span>:+UseZGC <span class="nt">-XX</span>:-ZGenerational ...
</code></pre></div></div>

<p>And you would get two warnings:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">The ZGenerational option is deprecated.</code></li>
  <li><code class="language-plaintext highlighter-rouge">Non-generational mode is deprecated.</code></li>
</ul>

<h4 id="more-information-6">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/474">JEP 474</a>.</p>

<h2 id="core-libraries">Core Libraries</h2>

<p>Java 23 also brings you 4 additions that are part of the core libraries:</p>

<ul>
  <li>Class-File API (Second Preview)</li>
  <li>Vector API (Eighth Incubator)</li>
  <li>Stream Gatherers (Second Preview)</li>
  <li>Deprecate the Memory-Access Methods in sun.misc.Unsafe for Removal</li>
</ul>

<h3 id="jep-466-class-file-api-second-preview">JEP 466: Class-File API (Second Preview)</h3>

<p>Java’s ecosystem relies heavily on the ability to parse, generate and transform class files. Frameworks use on-the-fly bytecode transformation to transparently add functionality, for example. These frameworks typically bundle class-file libraries like <a href="https://asm.ow2.io/">ASM</a> or <a href="https://www.javassist.org/">Javassist</a> to handle class file processing. However, they suffer from the fact that the six-month release cadence of the JDK causes the class-file format to evolve more quickly than before, meaning they might encounter class files that are newer than the class-file library that they bundle.</p>

<p>To solve this problem, JEP 466 proposes a standard class-file API that can produce class files that will always be up-to-date with the running JDK. This API will evolve together with the class-file format, enabling frameworks to rely solely on this API, rather than on the willingness of third-party developers to update and test their class-file libraries.</p>

<h4 id="elements-builders-and-transforms">Elements, Builders and Transforms</h4>

<p>The Class-File API, located in the <code class="language-plaintext highlighter-rouge">java.lang.classfile</code> package, consists of three main components:</p>

<dl>
  <dt><em>Elements</em></dt>
  <dd>Immutable descriptions of parts of a class file, such as instructions, attributes, fields, methods, or the entire file.</dd>
  <dt><em>Builders</em></dt>
  <dd>Corresponding builders for compound elements, offering specific building methods (e.g., <code class="language-plaintext highlighter-rouge">ClassBuilder::withMethod</code>) and serving as consumers of element types.</dd>
  <dt><em>Transforms</em></dt>
  <dd>Functions that take an element and a builder, determining if and how the element is transformed into other elements. This allows for flexible modification of class file elements.</dd>
</dl>

<h4 id="example-and-comparison-to-asm">Example and Comparison To ASM</h4>

<p>Suppose we wish to generate the following method in a class file:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">fooBar</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">z</span><span class="o">,</span> <span class="kt">int</span> <span class="n">x</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">z</span><span class="o">)</span>
        <span class="n">foo</span><span class="o">(</span><span class="n">x</span><span class="o">);</span>
    <span class="k">else</span>
        <span class="nf">bar</span><span class="o">(</span><span class="n">x</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<p>With ASM we could generate the method like so:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">ClassWriter</span> <span class="n">classWriter</span> <span class="o">=</span> <span class="o">...;</span>
<span class="nc">MethodVisitor</span> <span class="n">mv</span> <span class="o">=</span> <span class="n">classWriter</span><span class="o">.</span><span class="na">visitMethod</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="s">"fooBar"</span><span class="o">,</span> <span class="s">"(ZI)V"</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitCode</span><span class="o">();</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitVarInsn</span><span class="o">(</span><span class="no">ILOAD</span><span class="o">,</span> <span class="mi">1</span><span class="o">);</span>
<span class="nc">Label</span> <span class="n">label1</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Label</span><span class="o">();</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitJumpInsn</span><span class="o">(</span><span class="no">IFEQ</span><span class="o">,</span> <span class="n">label1</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitVarInsn</span><span class="o">(</span><span class="no">ALOAD</span><span class="o">,</span> <span class="mi">0</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitVarInsn</span><span class="o">(</span><span class="no">ILOAD</span><span class="o">,</span> <span class="mi">2</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitMethodInsn</span><span class="o">(</span><span class="no">INVOKEVIRTUAL</span><span class="o">,</span> <span class="s">"Foo"</span><span class="o">,</span> <span class="s">"foo"</span><span class="o">,</span> <span class="s">"(I)V"</span><span class="o">,</span> <span class="kc">false</span><span class="o">);</span>
<span class="nc">Label</span> <span class="n">label2</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Label</span><span class="o">();</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitJumpInsn</span><span class="o">(</span><span class="no">GOTO</span><span class="o">,</span> <span class="n">label2</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitLabel</span><span class="o">(</span><span class="n">label1</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitVarInsn</span><span class="o">(</span><span class="no">ALOAD</span><span class="o">,</span> <span class="mi">0</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitVarInsn</span><span class="o">(</span><span class="no">ILOAD</span><span class="o">,</span> <span class="mi">2</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitMethodInsn</span><span class="o">(</span><span class="no">INVOKEVIRTUAL</span><span class="o">,</span> <span class="s">"Foo"</span><span class="o">,</span> <span class="s">"bar"</span><span class="o">,</span> <span class="s">"(I)V"</span><span class="o">,</span> <span class="kc">false</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitLabel</span><span class="o">(</span><span class="n">label2</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitInsn</span><span class="o">(</span><span class="no">RETURN</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitEnd</span><span class="o">();</span>
</code></pre></div></div>

<p>Unlike in ASM, where clients directly create a <code class="language-plaintext highlighter-rouge">ClassWriter</code> and then request a <code class="language-plaintext highlighter-rouge">MethodVisitor</code>, the Class-File API adopts a different approach. Here, instead of clients initiating a builder through a constructor or factory, they supply a lambda function that takes a builder as its parameter:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">ClassBuilder</span> <span class="n">classBuilder</span> <span class="o">=</span> <span class="o">...;</span>
<span class="n">classBuilder</span><span class="o">.</span><span class="na">withMethod</span><span class="o">(</span><span class="s">"fooBar"</span><span class="o">,</span> <span class="nc">MethodTypeDesc</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="n">CD_void</span><span class="o">,</span> <span class="n">CD_boolean</span><span class="o">,</span> <span class="n">CD_int</span><span class="o">),</span> <span class="n">flags</span><span class="o">,</span>
                        <span class="n">methodBuilder</span> <span class="o">-&gt;</span> <span class="n">methodBuilder</span><span class="o">.</span><span class="na">withCode</span><span class="o">(</span><span class="n">codeBuilder</span> <span class="o">-&gt;</span> <span class="o">{</span>
    <span class="nc">Label</span> <span class="n">label1</span> <span class="o">=</span> <span class="n">codeBuilder</span><span class="o">.</span><span class="na">newLabel</span><span class="o">();</span>
    <span class="nc">Label</span> <span class="n">label2</span> <span class="o">=</span> <span class="n">codeBuilder</span><span class="o">.</span><span class="na">newLabel</span><span class="o">();</span>
    <span class="n">codeBuilder</span><span class="o">.</span><span class="na">iload</span><span class="o">(</span><span class="mi">1</span><span class="o">)</span>
        <span class="o">.</span><span class="na">ifeq</span><span class="o">(</span><span class="n">label1</span><span class="o">)</span>
        <span class="o">.</span><span class="na">aload</span><span class="o">(</span><span class="mi">0</span><span class="o">)</span>
        <span class="o">.</span><span class="na">iload</span><span class="o">(</span><span class="mi">2</span><span class="o">)</span>
        <span class="o">.</span><span class="na">invokevirtual</span><span class="o">(</span><span class="nc">ClassDesc</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"Foo"</span><span class="o">),</span> <span class="s">"foo"</span><span class="o">,</span> <span class="nc">MethodTypeDesc</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="n">CD_void</span><span class="o">,</span> <span class="n">CD_int</span><span class="o">))</span>
        <span class="o">.</span><span class="na">goto_</span><span class="o">(</span><span class="n">label2</span><span class="o">)</span>
        <span class="o">.</span><span class="na">labelBinding</span><span class="o">(</span><span class="n">label1</span><span class="o">)</span>
        <span class="o">.</span><span class="na">aload</span><span class="o">(</span><span class="mi">0</span><span class="o">)</span>
        <span class="o">.</span><span class="na">iload</span><span class="o">(</span><span class="mi">2</span><span class="o">)</span>
        <span class="o">.</span><span class="na">invokevirtual</span><span class="o">(</span><span class="nc">ClassDesc</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"Foo"</span><span class="o">),</span> <span class="s">"bar"</span><span class="o">,</span> <span class="nc">MethodTypeDesc</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="n">CD_void</span><span class="o">,</span> <span class="n">CD_int</span><span class="o">))</span>
        <span class="o">.</span><span class="na">labelBinding</span><span class="o">(</span><span class="n">label2</span><span class="o">);</span>
        <span class="o">.</span><span class="na">return_</span><span class="o">();</span>
<span class="o">});</span>
</code></pre></div></div>

<h4 id="whats-different-from-java-22-7">What’s Different From Java 22?</h4>

<p>Some refinements were made based on experience and feedback from the first preview stage; these are the most important ones:</p>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">CodeBuilder</code> class has been streamlined. This class has three kinds of factory methods for bytecode instructions: low-level factories, mid-level factories, and high-level builders for basic blocks. Based on feedback, mid-level methods that duplicated low-level methods or were infrequently used were removed, and the remaining mid-level methods were renamed to improve usability.</li>
  <li>The <code class="language-plaintext highlighter-rouge">AttributeMapper</code> instances in <code class="language-plaintext highlighter-rouge">Attributes</code> have been made accessible via static methods instead of static fields, to allow lazy initialization and reduce startup cost.</li>
  <li><code class="language-plaintext highlighter-rouge">Signature.TypeArg</code> has been remodeled to be an algebraic data type, to ease access to the bound type when the <code class="language-plaintext highlighter-rouge">TypeArg</code>’s kind is bounded.</li>
  <li>Type-aware <code class="language-plaintext highlighter-rouge">ClassReader::readEntryOrNull</code> and <code class="language-plaintext highlighter-rouge">ConstantPool::entryByIndex</code> methods have been added, which throw <code class="language-plaintext highlighter-rouge">ConstantPoolException</code> instead of <code class="language-plaintext highlighter-rouge">ClassCastException</code> if the entry at the index is not of the desired type. This allows class-file processors to indicate that a constant pool entry-type mismatch is a class-file format problem instead of the processor’s problem.</li>
</ul>

<p>Note that the Class-File API is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-7">More Information</h4>

<p>For more information on this feature, including the minor refinements and more details on transforming class files, see <a href="https://openjdk.org/jeps/466">JEP 466</a>.</p>

<h3 id="jep-469-vector-api-eighth-incubator">JEP 469: Vector API (Eighth Incubator)</h3>

<p>The Vector API makes it possible to express vector computations that reliably compile at runtime to optimal vector instructions. 
This means that these computations will significantly outperform equivalent scalar computations on the supported CPU architectures (x64 and AArch64).</p>

<h4 id="vector-computations-help-me-out-here">Vector Computations? Help Me Out Here!</h4>

<p>A <em>vector computation</em> is a mathematical operation on one or more one-dimensional matrices of an arbitrary length. Think of a vector as an array with a dynamic length. Furthermore, the elements in the vector can be accessed in constant time via indices, just like with an array.</p>

<p>In the past, Java programmers could only program such computations at the assembly-code level. But now that modern CPUs support advanced <a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">SIMD</a> features (Single Instruction, Multiple Data), it becomes more important to take advantage of the performance gains that SIMD instructions and multiple lanes operating in parallel can bring. The Vector API brings that possibility closer to the Java programmer.</p>

<h4 id="code-example">Code Example</h4>

<p>Here is a code example (taken from the JEP) that compares a simple scalar computation over elements of arrays with its equivalent using the Vector API:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">scalarComputation</span><span class="o">(</span><span class="kt">float</span><span class="o">[]</span> <span class="n">a</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">b</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">c</span><span class="o">)</span> <span class="o">{</span>
   <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="n">c</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">+</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">])</span> <span class="o">*</span> <span class="o">-</span><span class="mf">1.0f</span><span class="o">;</span>
   <span class="o">}</span>
<span class="o">}</span>

<span class="kd">static</span> <span class="kd">final</span> <span class="nc">VectorSpecies</span><span class="o">&lt;</span><span class="nc">Float</span><span class="o">&gt;</span> <span class="no">SPECIES</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">SPECIES_PREFERRED</span><span class="o">;</span>

<span class="kt">void</span> <span class="nf">vectorComputation</span><span class="o">(</span><span class="kt">float</span><span class="o">[]</span> <span class="n">a</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">b</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">c</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
    <span class="kt">int</span> <span class="n">upperBound</span> <span class="o">=</span> <span class="no">SPECIES</span><span class="o">.</span><span class="na">loopBound</span><span class="o">(</span><span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">);</span>
    <span class="k">for</span> <span class="o">(;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">upperBound</span><span class="o">;</span> <span class="n">i</span> <span class="o">+=</span> <span class="no">SPECIES</span><span class="o">.</span><span class="na">length</span><span class="o">())</span> <span class="o">{</span>
        <span class="c1">// FloatVector va, vb, vc;</span>
        <span class="kt">var</span> <span class="n">va</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">fromArray</span><span class="o">(</span><span class="no">SPECIES</span><span class="o">,</span> <span class="n">a</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
        <span class="kt">var</span> <span class="n">vb</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">fromArray</span><span class="o">(</span><span class="no">SPECIES</span><span class="o">,</span> <span class="n">b</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
        <span class="kt">var</span> <span class="n">vc</span> <span class="o">=</span> <span class="n">va</span><span class="o">.</span><span class="na">mul</span><span class="o">(</span><span class="n">va</span><span class="o">)</span>
                   <span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">vb</span><span class="o">.</span><span class="na">mul</span><span class="o">(</span><span class="n">vb</span><span class="o">))</span>
                   <span class="o">.</span><span class="na">neg</span><span class="o">();</span>
        <span class="n">vc</span><span class="o">.</span><span class="na">intoArray</span><span class="o">(</span><span class="n">c</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">for</span> <span class="o">(;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="n">c</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">+</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">])</span> <span class="o">*</span> <span class="o">-</span><span class="mf">1.0f</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>From the perspective of the Java developer, this is just another way of expressing scalar computations. It might come across as being more verbose, but on the other hand it can bring spectacular performance gains.</p>

<h4 id="typical-use-cases-1">Typical Use Cases</h4>

<p>The Vector API provides a way to write complex vector algorithms in Java that perform extremely well, such as vectorized <code class="language-plaintext highlighter-rouge">hashCode</code> implementations or specialized array comparisons. Numerous domains can benefit from this, including machine learning, linear algebra, encryption, text processing, finance, and code within the JDK itself.</p>

<h4 id="whats-different-from-java-22-8">What’s Different From Java 22?</h4>

<p>Compared to the seventh incubator version of this feature in Java 22, nothing was changed or added.
The Vector API will keep incubating until necessary features of Project Valhalla become available as preview features.
When that happens, the Vector API will be adapted to use them, and it will be promoted from incubation to preview.</p>

<h4 id="more-information-8">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/469">JEP 469</a>.</p>

<h3 id="jep-473-stream-gatherers-second-preview">JEP 473: Stream Gatherers (Second Preview)</h3>

<p>The Stream API has been around since Java 8 and it has definitely made its way into the heart of the typical Java developer. It enables a programming style that is both efficient and expressive. Recall that a stream pipeline consists of three parts: a source of elements, any number of intermediate operations, and a terminal operation. For example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Guitar</span><span class="o">&gt;</span> <span class="n">guitars</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span>
        <span class="k">new</span> <span class="nf">Guitar</span><span class="o">(</span><span class="s">"Cordoba F7 Paco Flamenco"</span><span class="o">,</span> <span class="nc">GuitarStyle</span><span class="o">.</span><span class="na">CLASSICAL</span><span class="o">),</span>
        <span class="k">new</span> <span class="nf">Guitar</span><span class="o">(</span><span class="s">"Taylor GS Mini-e Koa"</span><span class="o">,</span> <span class="nc">GuitarStyle</span><span class="o">.</span><span class="na">WESTERN</span><span class="o">),</span>
        <span class="k">new</span> <span class="nf">Guitar</span><span class="o">(</span><span class="s">"Gibson Les Paul Standard '50s Heritage Cherry Sunburst"</span><span class="o">,</span> <span class="nc">GuitarStyle</span><span class="o">.</span><span class="na">ELECTRIC</span><span class="o">),</span>
        <span class="k">new</span> <span class="nf">Guitar</span><span class="o">(</span><span class="s">"Fender Stratocaster"</span><span class="o">,</span> <span class="nc">GuitarStyle</span><span class="o">.</span><span class="na">ELECTRIC</span><span class="o">));</span>

<span class="kt">long</span> <span class="n">numberOfNonClassicalGuitars</span> <span class="o">=</span> <span class="n">guitars</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span> <span class="c1">// source of elements</span>
        <span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">g</span> <span class="o">-&gt;</span> <span class="nc">GuitarStyle</span><span class="o">.</span><span class="na">CLASSICAL</span> <span class="o">!=</span> <span class="n">g</span><span class="o">.</span><span class="na">guitarStyle</span><span class="o">())</span> <span class="c1">// intermediate operation</span>
        <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">counting</span><span class="o">());</span> <span class="c1">// terminal operation</span>
</code></pre></div></div>

<p>The Stream API offers a relatively diverse but predetermined range of intermediate and terminal operations, including mapping, filtering, reduction, sorting, and more. Over the years, many new intermediate operations have been suggested for the Stream API. For example, it could be useful to introduce a <code class="language-plaintext highlighter-rouge">distinctBy</code> intermediate operation. A <code class="language-plaintext highlighter-rouge">distinct</code> operation <em>does</em> exist, tracking the elements it has already seen by using object equality. But what if we want distinct elements based on something else than object equality?</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">singleGuitarPerStyle</span> <span class="o">=</span> <span class="n">guitars</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
                <span class="o">.</span><span class="na">distinctBy</span><span class="o">(</span><span class="nl">Guitar:</span><span class="o">:</span><span class="n">guitarStyle</span><span class="o">)</span> <span class="c1">// hypothetical</span>
                <span class="o">.</span><span class="na">toList</span><span class="o">();</span>
</code></pre></div></div>

<p>Over the years, many new intermediate operations have been suggested for the Stream API.
Most of the suggestions that were made would make sense when considered in isolation, but adding all of them would make the (already large) Stream API more difficult to learn because its operations would be less discoverable. A better alternative would be to introduce the ability to define custom intermediate operations, analogous to how the <code class="language-plaintext highlighter-rouge">Stream::collect</code> terminal operation currently is extensible, enabling the output of a pipeline to be summarized in a variety of ways.</p>

<p>So that is why this JEP proposes an API for custom intermediate operations that allows developers to transform finite and infinite streams in their own preferred ways.</p>

<h4 id="gatherers">Gatherers</h4>

<p><code class="language-plaintext highlighter-rouge">Stream::gather(Gatherer)</code> is a new intermediate stream operation that processes stream elements by applying a user-defined <em>gatherer</em>. One could say it is the dual of <code class="language-plaintext highlighter-rouge">Stream::collect(Collector)</code>, but for intermediate operations. Gatherers transform elements in different ways: one-to-one, one-to-many, many-to-one, or many-to-many. They can track previously seen elements, enable short-circuiting for infinite streams, and support parallel execution. For example, they may start by transforming one input element into one output element but switch to transforming one input element into two output elements based on a certain condition.</p>

<p>A gatherer implements the <code class="language-plaintext highlighter-rouge">java.util.stream.Gatherer</code> interface and is defined by four functions that work together:</p>

<dl>
  <dt><em><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.html#initializer()">initializer</a></em> (optional)</dt>
  <dd>Provides an object that maintains private state while processing stream elements.</dd>
  <dt><em><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.Integrator.html">integrator</a></em></dt>
  <dd>Integrates a new element from the input stream.</dd>
  <dt><em><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.html#combiner()">combiner</a></em> (optional)</dt>
  <dd>Evaluates the gatherer in parallel when the input stream is marked as such.</dd>
  <dt><em><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.html#finisher()">finisher</a></em> (optional)</dt>
  <dd>Is invoked when there are no more input elements to consume.</dd>
</dl>

<p>When <code class="language-plaintext highlighter-rouge">Stream::gather</code> is called, it roughly performs the following steps:</p>

<ul>
  <li>Create a <a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.Downstream.html"><code class="language-plaintext highlighter-rouge">Downstream</code></a> object which, when given an element of the gatherer’s output type, passes it to the next stage in the pipeline.</li>
  <li>Obtain the gatherer’s private state object by invoking the <code class="language-plaintext highlighter-rouge">get()</code> method of its initializer.</li>
  <li>Obtain the gatherer’s integrator by invoking its <a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.html#integrator()"><code class="language-plaintext highlighter-rouge">integrator()</code></a> method.</li>
  <li>While there are more input elements, invoke the integrator’s <a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.Integrator.html#integrate(A,T,java.util.stream.Gatherer.Downstream)"><code class="language-plaintext highlighter-rouge">integrate(...)</code></a> method, passing it the state object, the next element, and the downstream object. Terminate if that method returns false.</li>
  <li>Obtain the gatherer’s finisher and invoke it with the state and downstream objects.</li>
</ul>

<p>These steps are generic enough to allow every currently existing intermediate stream operation to be expressed in a custom gatherer. For example, the <code class="language-plaintext highlighter-rouge">Stream::map</code> operation turns each <code class="language-plaintext highlighter-rouge">T</code> element into a <code class="language-plaintext highlighter-rouge">U</code> element, so it is simply a stateless one-to-one gatherer. Likewise, the <code class="language-plaintext highlighter-rouge">Stream::filter</code> operation is a stateless one-to-many gatherer. This makes every stream pipeline conceptually equivalent to:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">stream</span>
    <span class="o">.</span><span class="na">gather</span><span class="o">(...)</span>
    <span class="o">.</span><span class="na">gather</span><span class="o">(...)</span>
    <span class="o">.</span><span class="na">gather</span><span class="o">(...)</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(...);</span>
</code></pre></div></div>

<h4 id="built-in-gatherers">Built-in gatherers</h4>

<p>As part of this JEP a few built-in gatherers are introduced:</p>

<dl>
  <dt><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#fold(java.util.function.Supplier,java.util.function.BiFunction)"><code class="language-plaintext highlighter-rouge">fold</code></a></dt>
  <dd>A stateful many-to-one gatherer which constructs an aggregate incrementally and emits that aggregate when no more input elements exist.</dd>
  <dt><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#mapConcurrent(int,java.util.function.Function)"><code class="language-plaintext highlighter-rouge">mapConcurrent</code></a></dt>
  <dd>A stateful one-to-one gatherer which invokes a supplied function for each input element concurrently, up to a supplied limit.</dd>
  <dt><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#scan(java.util.function.Supplier,java.util.function.BiFunction)"><code class="language-plaintext highlighter-rouge">scan</code></a></dt>
  <dd>A stateful one-to-one gatherer which applies a supplied function to the current state and the current element to produce the next element, which it passes downstream.</dd>
  <dt><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#windowFixed(int)"><code class="language-plaintext highlighter-rouge">windowFixed</code></a></dt>
  <dd>A stateful many-to-many gatherer which groups input elements into lists of a supplied size, emitting the windows downstream when they are full.</dd>
  <dt><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#windowSliding(int)"><code class="language-plaintext highlighter-rouge">windowSliding</code></a></dt>
  <dd>A stateful many-to-many gatherer which groups input elements into lists of a supplied size. After the first window, each subsequent window is created from a copy of its predecessor by dropping the first element and appending the next element from the input stream.</dd>
</dl>

<h4 id="example-of-a-custom-gatherer">Example of a Custom Gatherer</h4>

<p>Let’s look at a custom gatherer that implements the <code class="language-plaintext highlighter-rouge">distinctBy</code> operation we referred to earlier.</p>

<blockquote>
  <p>This example is based on Karl Heinz Marbaise’s <a href="https://blog.soebes.io/posts/2024/01/2024-01-07-jdk-gatherer/">excellent blog post on stream gatherers</a> - do check it out if you wish to know more!</p>
</blockquote>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="o">&lt;</span><span class="no">T</span><span class="o">,</span> <span class="no">A</span><span class="o">&gt;</span> <span class="nc">Gatherer</span><span class="o">&lt;</span><span class="no">T</span><span class="o">,</span> <span class="o">?,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="nf">distinctBy</span><span class="o">(</span><span class="nc">Function</span><span class="o">&lt;?</span> <span class="kd">super</span> <span class="no">T</span><span class="o">,</span> <span class="o">?</span> <span class="kd">extends</span> <span class="no">A</span><span class="o">&gt;</span> <span class="n">classifier</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">&lt;</span><span class="no">A</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="no">T</span><span class="o">&gt;&gt;&gt;</span> <span class="n">initializer</span> <span class="o">=</span> <span class="nl">HashMap:</span><span class="o">:</span><span class="k">new</span><span class="o">;</span>
    <span class="nc">Gatherer</span><span class="o">.</span><span class="na">Integrator</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">&lt;</span><span class="no">A</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="no">T</span><span class="o">&gt;&gt;,</span> <span class="no">T</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="n">integrator</span> <span class="o">=</span> <span class="o">(</span><span class="n">state</span><span class="o">,</span> <span class="n">element</span><span class="o">,</span> <span class="n">_</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="o">{</span>
        <span class="n">state</span><span class="o">.</span><span class="na">computeIfAbsent</span><span class="o">(</span><span class="n">classifier</span><span class="o">.</span><span class="na">apply</span><span class="o">(</span><span class="n">element</span><span class="o">),</span> <span class="n">_</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o">&lt;&gt;()).</span><span class="na">add</span><span class="o">(</span><span class="n">element</span><span class="o">);</span>
        <span class="k">return</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">// true, because more elements need to be consumed</span>
    <span class="o">};</span>
    <span class="nc">BiConsumer</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">&lt;</span><span class="no">A</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="no">T</span><span class="o">&gt;&gt;,</span> <span class="nc">Gatherer</span><span class="o">.</span><span class="na">Downstream</span><span class="o">&lt;?</span> <span class="kd">super</span> <span class="no">T</span><span class="o">&gt;&gt;</span> <span class="n">finisher</span> <span class="o">=</span> <span class="o">(</span><span class="n">state</span><span class="o">,</span> <span class="n">downstream</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="o">{</span>
        <span class="n">state</span><span class="o">.</span><span class="na">forEach</span><span class="o">((</span><span class="n">_</span><span class="o">,</span> <span class="n">value</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">downstream</span><span class="o">.</span><span class="na">push</span><span class="o">(</span><span class="n">value</span><span class="o">.</span><span class="na">getLast</span><span class="o">()));</span>
    <span class="o">};</span>
    <span class="k">return</span> <span class="nc">Gatherer</span><span class="o">.</span><span class="na">ofSequential</span><span class="o">(</span><span class="n">initializer</span><span class="o">,</span> <span class="n">integrator</span><span class="o">,</span> <span class="n">finisher</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<p>…and this is how you could use it:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">guitars</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
        <span class="o">.</span><span class="na">gather</span><span class="o">(</span><span class="n">distinctBy</span><span class="o">(</span><span class="nl">Guitar:</span><span class="o">:</span><span class="n">guitarStyle</span><span class="o">))</span>
        <span class="o">.</span><span class="na">forEach</span><span class="o">(</span><span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">::</span><span class="n">println</span><span class="o">);</span>
</code></pre></div></div>

<p>…which would yield the following output:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Guitar[name=Taylor GS Mini-e Koa, guitarStyle=WESTERN]
Guitar[name=Fender Stratocaster, guitarStyle=ELECTRIC]
Guitar[name=Cordoba F7 Paco Flamenco, guitarStyle=CLASSICAL]
</code></pre></div></div>

<h4 id="no-new-intermediate-operations">No New Intermediate Operations</h4>

<p>In conclusion the JEP also states that no new intermediate operations will be added to the <code class="language-plaintext highlighter-rouge">Stream</code> class to represent the newly-added built-in gatherers. This is because the language designers want the Stream API to remain concise and easy to learn. The JEP does suggest that adding new intermediate operations in a later round of preview could be an option, once they have proven that they are broadly useful.</p>

<h4 id="whats-different-from-java-22-9">What’s Different From Java 22?</h4>

<p>Compared to the preview version of this feature in Java 22, nothing was changed or added. JEP 473 simply exists to gather more feedback from users. Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-9">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/473">JEP 473</a>.</p>

<h3 id="jep-471-deprecate-the-memory-access-methods-in-sunmiscunsafe-for-removal">JEP 471: Deprecate the Memory-Access Methods in sun.misc.Unsafe for Removal</h3>

<p>The <code class="language-plaintext highlighter-rouge">sun.misc.Unsafe</code> class contains 87 methods to perform low-level operations, such as accessing off-heap memory.
The class is aptly named: using its methods without performing the necessary safety checks can lead to undefined behaviour and to the JVM crashing.
They were meant exclusively for use within the JDK, but back in 2002 when the class was introduced the <a href="https://openjdk.org/projects/jigsaw/">module system</a> wasn’t around yet and so there was no way to prevent the class from being used outside the JDK.
And so the memory-access methods in <code class="language-plaintext highlighter-rouge">sun.misc.Unsafe</code> became a valuable tool for library developers seeking greater power and performance than what standard APIs could provide.</p>

<p>Two standard APIs have emerged in recent years that are far better alternatives to these problematic methods:</p>

<ul>
  <li><a href="https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/invoke/VarHandle.html"><code class="language-plaintext highlighter-rouge">java.lang.invoke.VarHandle</code></a>, to manipulate on-heap memory safely and efficiently;</li>
  <li><a href="https://docs.oracle.com/en/java/javase/22/docs/api/java.base/java/lang/foreign/MemorySegment.html"><code class="language-plaintext highlighter-rouge">java.lang.foreign.MemorySegment</code></a>, to access off-heap memory safely and efficiently.</li>
</ul>

<p>Now that these APIs are available, the time has come to deprecate and eventually remove the memory-access methods in <code class="language-plaintext highlighter-rouge">sun.misc.Unsafe</code>.</p>

<h4 id="whats-different-from-java-22-10">What’s Different From Java 22?</h4>

<p>All uses of memory-access methods in <code class="language-plaintext highlighter-rouge">sun.misc.Unsafe</code> will generate compile-time deprecation warnings in JDK 23. In a future release of Java, warnings at run time will be issued, and at an even later stage exceptions will be thrown. Finally, the methods will be removed entirely. According to the JEP text the process won’t be completed until the release of JDK 26, giving developers ample time to adjust to the new situation.</p>

<h4 id="more-information-10">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/471">JEP 471</a>. It has more details on the targeted methods, their alternatives from <code class="language-plaintext highlighter-rouge">VarHandle</code> and <code class="language-plaintext highlighter-rouge">MemorySegment</code> and how to configure the deprecation warnings with the new command-line option <code class="language-plaintext highlighter-rouge">--sun-misc-unsafe-memory-access</code> (to promote the warnings to <code class="language-plaintext highlighter-rouge">UnsupportedOperationException</code>s already, for example). It also provides a few migration examples.</p>

<h2 id="tools">Tools</h2>

<p>Java 23 contains a single feature that is part of the JavaDoc tool:</p>

<ul>
  <li>Markdown Documentation Comments</li>
</ul>

<h3 id="jep-467-markdown-documentation-comments">JEP 467: Markdown Documentation Comments</h3>

<p>The JavaDoc documentation standard has been part of Java since its inception in 1995.
Back then, HTML was the obvious choice when JavaDoc needed a way to support basic markup.
Nowadays HTML is far less likely to be manually produced by humans, but rather generated from some other markup language that is more suitable for humans.
Coupled with the fact that inline JavaDoc tags (like <code class="language-plaintext highlighter-rouge">{@link}</code> and <code class="language-plaintext highlighter-rouge">{@code}</code>) are not that familiar to developers, it makes perfect sense that Java’s documentation tool will start supporting Markdown!</p>

<p>Markdown documentation comments use the <code class="language-plaintext highlighter-rouge">///</code> prefix instead of the familiar <code class="language-plaintext highlighter-rouge">/**</code> one. This is due to two reasons:</p>

<ol>
  <li>Block comments that begin with <code class="language-plaintext highlighter-rouge">/*</code> cannot contain the <code class="language-plaintext highlighter-rouge">*/</code> character sequence. This makes it currently very difficult to include code examples that contain embedded <code class="language-plaintext highlighter-rouge">/* ... */</code> comments. In <code class="language-plaintext highlighter-rouge">//</code> comments there’s no such restriction.</li>
  <li>A traditional documentation comment (starting with <code class="language-plaintext highlighter-rouge">/**</code>) doesn’t require the leading whitespace and the asterisk character on each line. In these cases, Markdown constructs that uses asterisks (like emphasis or list items) would clash with the traditional documentation comment syntax.</li>
</ol>

<h4 id="example-of-the-differences">Example of the Differences</h4>

<p>To illustrate how documentation comments can change now that Markdown is supported, here’s an example diff screenshot from the JEP:</p>

<p><img src="https://cr.openjdk.org/~jjg/Object-hashcode-diff-3.png" alt="Differences between regular documentation comment and Markdown documentation comment" /></p>

<h4 id="syntax">Syntax</h4>

<p>Markdown documentation comments are written in the <a href="https://spec.commonmark.org/0.30">CommonMark</a> variant of Markdown. Simple tables are supported, using the syntax of <a href="https://github.github.com/gfm/">GitHub Flavored Markdown</a>. For example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/// | Make     | Model      |
/// |----------|------------|
/// | Fender   | Telecaster |
/// | Gibson   | Les Paul   |
/// | Epiphone | Casino     |
</code></pre></div></div>

<p>You can create a link to an element declared elsewhere in your API, by simply enclosing a reference to the element in square brackets. 
For example, to link to <code class="language-plaintext highlighter-rouge">java.util.List</code>, you can write <code class="language-plaintext highlighter-rouge">[java.util.List]</code>, or just <code class="language-plaintext highlighter-rouge">[List]</code>.
The link is equivalent to using the standard JavaDoc <code class="language-plaintext highlighter-rouge">{@link ...}</code> tag.</p>

<p>You can link to any kind of program element:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/// - a module [com.hannotify.guitarstore/]
/// - a package [com.hannotify.guitarstore.products]
/// - a class [Guitar]
/// - a field [Guitar#name]
/// - a method [Guitar#isInTune()]
</code></pre></div></div>

<p>To create a link with alternative text, you can use the form [text][element]. For example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/// Please feel free to use our [utility guitar tuning method][Guitar#isInTune()]!
</code></pre></div></div>

<h4 id="whats-different-from-java-22-11">What’s Different From Java 22?</h4>

<p>In Java 22, it wasn’t yet possible to include Markdown in documentation comments. This possibility has been added in Java 23.</p>

<h4 id="more-information-11">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/467">JEP 467</a>.</p>

<h2 id="final-thoughts">Final thoughts</h2>

<p>This release of Java didn’t have as many new features as previous versions, but there’s still more than enough going on in our favourite language. Project Amber is still going strong, making Java more expressive and elegant. String templates might be missing from this release, but its omission shows that the preview process is working as intended. We can look forward to getting a redesigned version in the future. Also, Java is becoming friendlier towards newcomers now that beginner programs can be shorter than before. And that’s not all that’s new: <a href="https://jdk.java.net/23/release-notes">many other updates</a> were included in this release, including thousands of performance, stability and security updates. So what are you waiting for? Time to take this brand-new Java version for a test drive!</p>]]></content><author><name>Hanno Embregts</name></author><category term="java" /><summary type="html"><![CDATA[Java 23 has arrived, and it brings a truckload of changes! For example, in JavaDoc, 'Markdown documentation comments' are now supported. On top of that, a lot of features have been re-previewed and there are also two brand-new ones - module import declarations and primitive type patterns. This post has all the info!]]></summary></entry><entry><title type="html">How Java Keeps Reinventing Itself</title><link href="https://hanno.codes/2024/05/30/how-java-keeps-reinventing-itself-interview/" rel="alternate" type="text/html" title="How Java Keeps Reinventing Itself" /><published>2024-05-30T18:30:00+00:00</published><updated>2024-05-30T18:30:00+00:00</updated><id>https://hanno.codes/2024/05/30/how-java-keeps-reinventing-itself-interview</id><content type="html" xml:base="https://hanno.codes/2024/05/30/how-java-keeps-reinventing-itself-interview/"><![CDATA[<p>I was interviewed by ‘Anne’, a custom version of GPT-4 that was developed at Info Support. Anne was provided with my <a href="/about-me">bio</a> and the interview topic “Some people think Java is less relevant nowadays, but actually a lot of work is  being done to make sure the language remains modern and relevant.” From that, Anne generated the first question and came up with seven additional ones based on the answers I gave. I think it turned out to be a good read, so I’m happy to share it here.</p>

<p><img src="/assets/images/blog/new-invention.jpg" alt="New invention" /></p>
<blockquote>
  <p>Image from <a href="https://pxhere.com/en/photo/909565">PxHere</a></p>
</blockquote>

<h2 id="-anne-what-makes-java-a-relevant-programming-language-in-this-day-and-age">🤖 Anne: What makes Java a relevant programming language in this day and age?</h2>

<p><strong>Hanno:</strong> I can think of several reasons. By far the most important is the release cadence that Java has been using since 2017. Every six months, a new version of Java is released. This means that new features become available to developers much faster than before.</p>

<p>Another reason has to do with the popularity of the JVM. It forms an abstraction layer on top of the operating system, and was originally designed to execute Java code on any platform. However, today there are several programming languages that work on the JVM, including Groovy, Scala, and Kotlin. This exposes the users of these languages to the JVM, which leads to a growing popularity of the Java platform as a whole.</p>

<h2 id="-anne-how-does-the-faster-release-cadence-affect-java-developers-does-it-bring-any-challenges-as-well">🤖 Anne: How does the faster release cadence affect Java developers? Does it bring any challenges as well?</h2>

<p><strong>Hanno:</strong> Before 2017, a new Java version would not get released until all features that targeted that release were completed. Today new features become available every six months. I think this has a positive impact on developers’ motivation, because they get to try out new things twice a year.</p>

<p>There are challenges, though. Larger features are now split into parts, and the corresponding APIs are often not yet finalized. These “preview features” require a special Java setting to be used. The goal is to quickly gather feedback and make necessary adjustments to the features. This also means that a preview feature in a later version may work differently in a subtle way. This is why the term “preview feature” was created, to remind developers that the feature might still change a bit.</p>

<h2 id="-anne-can-you-provide-an-example-where-the-preview-feature-approach-has-led-to-improvements-based-on-feedback">🤖 Anne: Can you provide an example where the ‘preview feature’ approach has led to improvements based on feedback?</h2>

<p><strong>Hanno:</strong> In the case of the <a href="https://openjdk.org/jeps/441">Pattern Matching for switch</a> feature, the designers initially proposed ‘guarded patterns’, which include an additional boolean expression after a pattern match. The syntax was a double ampersand (<code class="language-plaintext highlighter-rouge">&amp;&amp;</code>) in Java 18. Users provided feedback that they found this confusing, especially when the boolean expression itself also contained <code class="language-plaintext highlighter-rouge">&amp;&amp;</code> or <code class="language-plaintext highlighter-rouge">||</code> operations. So in Java 19, guarded patterns were replaced by ‘when clauses’, with the double ampersand being replaced by the keyword <code class="language-plaintext highlighter-rouge">when</code>.</p>

<h2 id="-anne-can-you-describe-a-situation-where-the-jvm-has-contributed-to-solving-a-technical-problem-and-how-do-scala-and-kotlin-contribute-to-the-popularity-of-java">🤖 Anne: Can you describe a situation where the JVM has contributed to solving a technical problem? And how do Scala and Kotlin contribute to the popularity of Java?</h2>

<p><strong>Hanno:</strong> The primary reason for the existence of the JVM has always been the ability to write software that works on all operating systems. The motto was ‘write once, run anywhere’. Scala and Kotlin do not necessarily make Java as a language more popular. However, they do contribute to the popularity of the broader Java platform. Developers of these languages encounter the same tools and libraries, such as Maven, Spring, and Jenkins. This makes a potential transition to Java in the future easier. Additionally, the languages have a positive effect on each other. New Java features are often based on similar ideas from Scala and Kotlin, and vice versa.</p>

<h2 id="-anne-how-do-you-see-the-future-of-java-with-the-rise-of-python-and-javascript-will-it-remain-relevant">🤖 Anne: How do you see the future of Java with the rise of Python and JavaScript? Will it remain relevant?</h2>

<p><strong>Hanno:</strong> JavaScript is mainly used for front-end development, so its use case differs from Java. Python, like Java, is intended for back-end development and has a large market share in data analysis. Java, on the other hand, is popular for web applications using REST and HTML, for example. So, the languages have each carved out their own niche. I believe they can coexist well and are unlikely to lose their relevance quickly.</p>

<h2 id="-anne-what-advice-would-you-give-to-a-beginner-developer-who-wants-to-learn-java">🤖 Anne: What advice would you give to a beginner developer who wants to learn Java?</h2>

<p><strong>Hanno:</strong> This is a perfect time to start learning Java! Many useful constructs are currently being added to Java through <a href="https://openjdk.org/projects/amber/">Project Amber</a>, which make Java more powerful and versatile. The Java 21 feature <a href="https://openjdk.org/jeps/445">Unnamed Classes and Instance Main Methods</a> is also relevant for beginners, as it makes it easier to write a first ‘Hello World!’ program. I expect these developments to significantly lower the barrier for beginner Java developers.</p>

<h2 id="-anne-which-resources-or-learning-paths-do-you-recommend-to-master-java">🤖 Anne: Which resources or learning paths do you recommend to master Java?</h2>

<p><strong>Hanno:</strong> The Oracle website <a href="https://dev.java">dev.java</a> is a very good starting point. Here you can find tutorials, documentation, an online Java parser, and recordings by experts. The book <a href="https://a.co/d/83xQMBc">Effective Java by Joshua Bloch</a> is also very valuable. I learned a lot from it. After you’ve grasped the basics of object-oriented programming with Java, I highly recommend to read this book.</p>

<h2 id="-anne-how-do-you-see-the-future-of-the-it-industry-and-the-role-of-java-in-it">🤖 Anne: How do you see the future of the IT industry and the role of Java in it?</h2>

<p><strong>Hanno:</strong> I am confident that Java will continue to keep pace with technological advancements. A good example of this is the strong support for generative AI that IDEs like IntelliJ IDEA and Visual Studio Code have added. Additionally, <a href="https://devm.io/java/energy-efficient-programming-languages-137264">Java is a relatively energy-efficient language</a>. Energy efficiency is becoming increasingly relevant in the climate crisis that is looming, and I believe the availability of sustainable energy will be crucial. Because the most sustainable energy is the energy you don’t consume, I am convinced Java’s energy efficiency will make the language even more relevant in the future.</p>

<h2 id="acknowledgements">Acknowledgements</h2>

<p>This interview was originally published in Dutch on the <a href="https://carriere.infosupport.com/resources/hoe-java-zichzelf-opnieuw-uitvindt">Info Support website</a> and has been translated and published here with permission.</p>]]></content><author><name>Hanno Embregts</name></author><category term="java" /><category term="sustainability" /><summary type="html"><![CDATA[IT professionals sometimes get the impression that Java is a technically less advanced or outdated languange. But it turns out the exact opposite is true. I was interviewed on this topic by Info Support's AI interviewer 'Anne'. Keep reading to find out why Java is still relevant in this day and age.]]></summary></entry><entry><title type="html">Java 22 Is Here, And It’s Ready To Rock</title><link href="https://hanno.codes/2024/03/19/java-22-is-here/" rel="alternate" type="text/html" title="Java 22 Is Here, And It’s Ready To Rock" /><published>2024-03-19T02:30:00+00:00</published><updated>2024-03-19T02:30:00+00:00</updated><id>https://hanno.codes/2024/03/19/java-22-is-here</id><content type="html" xml:base="https://hanno.codes/2024/03/19/java-22-is-here/"><![CDATA[<p>Java 22 is here! It’s been six months since Java 21 was released, so it’s time for another fresh set of Java features. This post takes you on a tour of the JEPs that are part of this release, giving you a brief introduction to each of them. Where applicable the differences with Java 21 are highlighted and a few typical use cases are provided, so that you’ll be more than ready to use these features after reading this!</p>

<p><img src="/assets/images/blog/guitar-pedals.jpg" alt="Java 22 - Ready to rock!" /></p>
<blockquote>
  <p>Image from <a href="https://pxhere.com/en/photo/680220">PxHere</a></p>
</blockquote>

<h2 id="from-project-amber">From Project Amber</h2>

<p>Java 22 contains four features that originated from <a href="https://openjdk.org/projects/amber/">Project Amber</a>:</p>

<ul>
  <li>Statements before super(…)</li>
  <li>Unnamed Variables &amp; Patterns</li>
  <li>String Templates</li>
  <li>Implicitly Declared Classes and Instance Main Methods</li>
</ul>

<blockquote>
  <p>The goal of Project Amber is to explore and incubate smaller, productivity-oriented Java language features.</p>
</blockquote>

<h3 id="jep-447-statements-before-super-preview">JEP 447: Statements before super(…) (Preview)</h3>

<p>In Java, constructors run from top to bottom. On top of that, a superclass constructor must finish initializing its fields before a subclass constructor starts. This ensures proper object state initialization and prevents access to uninitialized fields. Java enforces this by requiring explicit constructor calls to be the first statement in a constructor body, and constructor arguments cannot access the current object. While these rules ensure that constructors behave predictably, they may restrict the use of common programming patterns in constructor methods. The following code example illustrates this point:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">StringQuartet</span> <span class="kd">extends</span> <span class="nc">Orchestra</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="nf">StringQuartet</span><span class="o">(</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Instrument</span><span class="o">&gt;</span> <span class="n">instruments</span><span class="o">)</span> <span class="o">{</span>
        <span class="kd">super</span><span class="o">(</span><span class="n">instruments</span><span class="o">);</span> <span class="c1">// Potentially unnecessary work!</span>

        <span class="k">if</span> <span class="o">(</span><span class="n">instruments</span><span class="o">.</span><span class="na">size</span><span class="o">()</span> <span class="o">!=</span> <span class="mi">4</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalArgumentException</span><span class="o">(</span><span class="s">"Not a quartet!"</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>It would be better to let the constructor fail fast, by validating its arguments before the <code class="language-plaintext highlighter-rouge">super(...)</code> constructor is called.
Pre-Java 22, we could only achieve this by introducing a <code class="language-plaintext highlighter-rouge">static</code> method that acts upon the value passed to the super constructor.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">StringQuartet</span> <span class="kd">extends</span> <span class="nc">Orchestra</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="nf">StringQuartet</span><span class="o">(</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Instrument</span><span class="o">&gt;</span> <span class="n">instruments</span><span class="o">)</span> <span class="o">{</span>
        <span class="kd">super</span><span class="o">(</span><span class="n">validate</span><span class="o">(</span><span class="n">instruments</span><span class="o">));</span>
    <span class="o">}</span>

    <span class="kd">private</span> <span class="kd">static</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Instrument</span><span class="o">&gt;</span> <span class="nf">validate</span><span class="o">(</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Instrument</span><span class="o">&gt;</span> <span class="n">instruments</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">instruments</span><span class="o">.</span><span class="na">size</span><span class="o">()</span> <span class="o">!=</span> <span class="mi">4</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalArgumentException</span><span class="o">(</span><span class="s">"Not a quartet!"</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>But a far more readable way to write the same would be:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">StringQuartet</span> <span class="kd">extends</span> <span class="nc">Orchestra</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="nf">StringQuartet</span><span class="o">(</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Instrument</span><span class="o">&gt;</span> <span class="n">instruments</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">if</span> <span class="o">(</span><span class="n">instruments</span><span class="o">.</span><span class="na">size</span><span class="o">()</span> <span class="o">!=</span> <span class="mi">4</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nf">IllegalArgumentException</span><span class="o">(</span><span class="s">"Not a quartet!"</span><span class="o">);</span>
        <span class="o">}</span>

        <span class="kd">super</span><span class="o">(</span><span class="n">instruments</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This approach will be possible in Java 22, due to the introduction of <em>pre-construction contexts</em>.
Java used to treat the arguments to an explicit constructor invocation to be in a <em>static context</em>, as if they were in a static method. But this restriction is a bit stronger than necessary, which is why Java 22 introduces the aforementioned <em>pre-construction contexts</em>; a strictly weaker concept. It covers both the arguments to an explicit constructor invocation and any statements that occur before it. Within a pre-construction context, the rules are similar to normal instance methods, except that the code may not access the instance under construction.</p>

<h4 id="whats-different-from-java-21">What’s Different From Java 21?</h4>

<p>In Java 21 and earlier, statements were not allowed to appear before an explicit constructor invocation. In Java 22 such constructions are now valid, but only if these statements don’t reference the instance being created.</p>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information">More Information</h4>

<p>The JEP contains a few more details on the restrictions of instance accessing in a pre-construction context. See <a href="https://openjdk.org/jeps/447">JEP 447</a> to learn more.</p>

<p>Or if you want to try out ‘statements before super(…)’ for yourself, then here’s a <a href="https://github.com/hannotify/java-22-release-day">GitHub repository</a> to get you started.</p>

<h3 id="jep-456-unnamed-variables--patterns">JEP 456: Unnamed Variables &amp; Patterns</h3>

<p>Data processing in Java has become increasingly streamlined since the introduction of <a href="https://openjdk.org/jeps/395">records</a> and <a href="https://openjdk.org/jeps/440">record patterns</a>. But writing out an entire record pattern when some record components aren’t even used in the logic that follows can be both cumbersome and confusing. Consider the following code example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="kt">boolean</span> <span class="nf">isDelayTimeEqualToReverbRoomSize</span><span class="o">(</span><span class="nc">EffectLoop</span> <span class="n">effectLoop</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">effectLoop</span> <span class="k">instanceof</span> <span class="nf">EffectLoop</span><span class="o">(</span><span class="nc">Delay</span><span class="o">(</span><span class="kt">int</span> <span class="n">timeInMs</span><span class="o">),</span> <span class="nc">Reverb</span><span class="o">(</span><span class="nc">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">int</span> <span class="n">roomSize</span><span class="o">)))</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">timeInMs</span> <span class="o">==</span> <span class="n">roomSize</span><span class="o">;</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This piece of code, which originates from a <a href="https://github.com/hannotify/pattern-matching-music-store">music store example repository</a>, deals with comparing two guitar effects that are stored in the <code class="language-plaintext highlighter-rouge">EffectLoop</code> that the fictional guitar player is currently using.<br />
Here, the logic in the <code class="language-plaintext highlighter-rouge">if</code> body doesn’t reference the <code class="language-plaintext highlighter-rouge">name</code> whatsoever, but for a long time Java didn’t have a way to indicate this as an intentional omission. 
And so we’ve had no choice but to specify the entire record pattern, leading future readers of this code to doubt the correctness of the implementation.</p>

<h4 id="unnamed-patterns">Unnamed Patterns</h4>

<p>This situation was changed in Java 21, when <em>unnamed patterns</em> became available through <a href="https://openjdk.org/jeps/443">JEP 443</a>, a feature that will be finalized in Java 22. Let’s see how an unnamed pattern would change the example code we presented earlier:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="kt">boolean</span> <span class="nf">isDelayTimeEqualToReverbRoomSize</span><span class="o">(</span><span class="nc">EffectLoop</span> <span class="n">effectLoop</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">effectLoop</span> <span class="k">instanceof</span> <span class="nf">EffectLoop</span><span class="o">(</span><span class="nc">Delay</span><span class="o">(</span><span class="kt">int</span> <span class="n">timeInMs</span><span class="o">),</span> <span class="nc">Reverb</span><span class="o">(</span><span class="n">_</span><span class="o">,</span> <span class="kt">int</span> <span class="n">roomSize</span><span class="o">)))</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">timeInMs</span> <span class="o">==</span> <span class="n">roomSize</span><span class="o">;</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The underscore denotes the unnamed pattern here: it is an unconditional pattern which binds nothing. You can use it to indicate that it doesn’t matter to what first value the pattern matches the <code class="language-plaintext highlighter-rouge">Reverb</code>, as long as the second parameter is matched to an <code class="language-plaintext highlighter-rouge">int</code>.</p>

<h4 id="unnamed-pattern-variables">Unnamed Pattern Variables</h4>

<p>Java 21 also introduced <em>unnamed pattern variables</em>, a feature that is also finalized in Java 22. You can use an unnamed pattern variable whenever you care about the <em>type</em> your record pattern will match, but when you don’t need any <em>value</em> bound to it. Now imagine our fictional guitar player wants to use their tuner effect pedal to also support tuning notes played on a piano. In that case we could use unnamed pattern variables like this:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="kt">void</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">,</span> <span class="nc">Piano</span> <span class="n">piano</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="k">switch</span><span class="o">(</span><span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">case</span> <span class="nf">Tuner</span><span class="o">(</span><span class="nc">FlatNote</span> <span class="n">_</span><span class="o">),</span> <span class="nc">Tuner</span><span class="o">(</span><span class="nc">SharpNote</span> <span class="n">_</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="s">"Tuning one of the black keys..."</span><span class="o">;</span>
        <span class="k">case</span> <span class="nf">Tuner</span><span class="o">(</span><span class="nc">RegularNote</span> <span class="n">_</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="s">"Tuning one of the white keys..."</span><span class="o">;</span>
        <span class="k">default</span> <span class="o">-&gt;</span> <span class="s">"An unknown effect is active..."</span><span class="o">;</span>
    <span class="o">});</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here, we execute specific logic when we encounter a tuner that tunes a flat (♭) or sharp (♯) note. An unnamed pattern variable is the appropriate choice here, because the logic acts on the matched type only - meaning its value can be safely ignored.</p>

<h4 id="unnamed-variables">Unnamed Variables</h4>

<p><em>Unnamed variables</em> can be useful in situations where variables are unused and their names are irrelevant, for example when keeping a counter variable within the body of a for-each loop:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">guitarCount</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
<span class="k">for</span> <span class="o">(</span><span class="nc">Guitar</span> <span class="n">guitar</span> <span class="o">:</span> <span class="n">guitars</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">guitarCount</span> <span class="o">&lt;</span> <span class="no">LIMIT</span><span class="o">)</span> <span class="o">{</span> 
        <span class="n">guitarCount</span><span class="o">++;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">guitar</code> variable is declared and populated here, but it is never used. Unfortunately, its intentional non-use doesn’t come across as such to the reader. Moreover, static code analysis tools like Sonar will probably complain about the unused variable, raising suspicions even more. An unnamed variable better conveys the intent of the code:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">guitarCount</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
<span class="k">for</span> <span class="o">(</span><span class="nc">Guitar</span> <span class="n">_</span> <span class="o">:</span> <span class="n">guitars</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">guitarCount</span> <span class="o">&lt;</span> <span class="no">LIMIT</span><span class="o">)</span> <span class="o">{</span> 
        <span class="n">guitarCount</span><span class="o">++;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Another good example is handling exceptions in a generic way:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">lesPaul</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Guitar</span><span class="o">(</span><span class="s">"Les Paul"</span><span class="o">,</span> <span class="nc">GuitarStyle</span><span class="o">.</span><span class="na">ELECTRIC</span><span class="o">);</span>
<span class="k">try</span> <span class="o">{</span> 
    <span class="n">cart</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">stock</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">lesPaul</span><span class="o">,</span> <span class="n">guitarCount</span><span class="o">));</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">OutOfStockException</span> <span class="n">_</span><span class="o">)</span> <span class="o">{</span> 
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Sorry, out of stock!"</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Keep in mind that unnamed variables only make sense when they’re not visible outside a method, so they currently only work with local variables, exception parameters and lambda parameters. The theoretical concept of <em>unnamed method parameters</em> is briefly touched upon in the JEP, but supporting it comes with enough challenges to at least warrant postponing it to a future JEP.</p>

<h4 id="whats-different-from-java-21-1">What’s Different From Java 21?</h4>

<p>Compared to the preview version of this feature in Java 21, nothing was changed or added. JEP 456 simply exists to finalize the feature.</p>

<h4 id="more-information-1">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/456">JEP 456</a>.</p>

<h3 id="jep-459-string-templates-second-preview">JEP 459: String Templates (Second Preview)</h3>

<p>Several options in Java currently exist to compose a string from literal text and expressions:</p>

<ul>
  <li>String concatenation with the <code class="language-plaintext highlighter-rouge">+</code> operator;</li>
  <li><code class="language-plaintext highlighter-rouge">StringBuilder</code>;</li>
  <li><code class="language-plaintext highlighter-rouge">String::format</code> or <code class="language-plaintext highlighter-rouge">String::formatted</code>;</li>
  <li><code class="language-plaintext highlighter-rouge">java.text.MessageFormat</code></li>
</ul>

<p>However, these mechanisms come with drawbacks. They involve hard-to-read code (<code class="language-plaintext highlighter-rouge">+</code> operator) or verbose code (<code class="language-plaintext highlighter-rouge">StringBuilder</code>), they separate the input string from the parameters (<code class="language-plaintext highlighter-rouge">String::format</code>) or require a lot of ceremony (<code class="language-plaintext highlighter-rouge">MessageFormat</code>).</p>

<p><em>String interpolation</em> is a mechanism that many programming languages offer instead. But it comes with a drawback of its own: interpolated strings need to be manually validated by the developer to avoid dangerous risks like <a href="https://en.wikipedia.org/wiki/SQL_injection">SQL injection</a>.</p>

<p>This JEP re-previews the ‘String Templates’ feature: a template-based mechanism for composing strings that offers the benefits of interpolation, but is less prone to introducing security vulnerabilities. A <em>template expression</em> is a new kind of expression in Java that can perform string interpolation, but it’s also programmable so that developers can compose strings safely and efficiently.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">guitarType</span> <span class="o">=</span> <span class="s">"Les Paul"</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">STR</span><span class="o">.</span><span class="s">"I bought a \{guitarType} yesterday."</span><span class="o">);</span>
<span class="c1">// outputs "I bought a Les Paul yesterday."</span>
</code></pre></div></div>

<p>The template expression <code class="language-plaintext highlighter-rouge">STR."I bought a \{guitarType} yesterday."</code> consists of:</p>

<ul>
  <li>A template processor (<code class="language-plaintext highlighter-rouge">STR</code>);</li>
  <li>A dot character, as seen in other kinds of expressions; and</li>
  <li>A template (<code class="language-plaintext highlighter-rouge">"I bought a \{guitarType} yesterday."</code>), which contains an embedded expression (<code class="language-plaintext highlighter-rouge">\{guitarType}</code>).</li>
</ul>

<p>When a template expression is evaluated at run time, its template processor combines the literal text in the template with the values of the embedded expressions to produce a result. The embedded expressions can perform arithmetic, invoke methods and access fields:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">price</span> <span class="o">=</span> <span class="mi">12</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">STR</span><span class="o">.</span><span class="s">"A set of strings costs \{price} dollars; so each string costs \{price / 6} dollars."</span><span class="o">);</span>
<span class="c1">// outputs "A set of strings costs 12 dollars; so each string costs 2 dollars."</span>
</code></pre></div></div>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">record</span> <span class="nf">Guitar</span><span class="o">(</span><span class="nc">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">inTune</span><span class="o">)</span> <span class="o">{}</span>
<span class="kd">class</span> <span class="nc">GuitarTuner</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">...</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="kt">var</span> <span class="n">guitar</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Guitar</span><span class="o">(</span><span class="s">"Gibson Les Paul Standard '50s Heritage Cherry Sunburst"</span><span class="o">,</span> <span class="kc">false</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">STR</span><span class="o">.</span><span class="s">"This guitar is \{guitar.inTune() ? "" : "</span><span class="n">not</span><span class="s">"} in tune."</span><span class="o">);</span>
        <span class="c1">// outputs "This guitar is not in tune.</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>As you can see, double-quote characters can be used inside embedded expressions without escaping them, making the switch from concatenation to template expressions easier. Multi-line template expressions are also possible; they use a syntax similar to that of <a href="https://docs.oracle.com/javase/specs/jls/se20/html/jls-3.html#jls-3.10.6">text blocks</a>:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">title</span> <span class="o">=</span> <span class="s">"My Online Guitar Store"</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">text</span> <span class="o">=</span> <span class="s">"Buy your next Les Paul here!"</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">html</span> <span class="o">=</span> <span class="no">STR</span><span class="o">.</span><span class="s">"""
        &lt;html&gt;
          &lt;head&gt;
            &lt;title&gt;\{title}&lt;/title&gt;
          &lt;/head&gt;
          &lt;body&gt;
            &lt;p&gt;\{text}&lt;/p&gt;
          &lt;/body&gt;
        &lt;/html&gt;
        """</span><span class="o">;</span>
</code></pre></div></div>

<h4 id="template-processors">Template Processors</h4>

<p><code class="language-plaintext highlighter-rouge">STR</code> is a template processor defined in the Java Platform. It performs string interpolation by replacing each embedded expression in the template with the (stringified) value of that expression. It is a <code class="language-plaintext highlighter-rouge">public static final</code> field that is automatically imported into every Java source file.</p>

<p>More template processors exist:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">FMT</code> - besides performing interpolation, it also interprets format specifiers which appear to the left of embedded expressions. The format specifiers are the same as those defined in <code class="language-plaintext highlighter-rouge">java.util.Formatter</code>.</li>
  <li><code class="language-plaintext highlighter-rouge">RAW</code> - a standard template processor that produces an unprocessed <code class="language-plaintext highlighter-rouge">StringTemplate</code> object.</li>
</ul>

<h4 id="ensuring-safety">Ensuring Safety</h4>

<p>The construct <code class="language-plaintext highlighter-rouge">STR."..."</code> we used so far is actually a shorthand for defining a template and calling its <code class="language-plaintext highlighter-rouge">process</code> method, meaning that the first code example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">guitarType</span> <span class="o">=</span> <span class="s">"Les Paul"</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">STR</span><span class="o">.</span><span class="s">"I bought a \{guitarType} yesterday."</span><span class="o">);</span>
</code></pre></div></div>

<p>is equivalent to:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">guitarType</span> <span class="o">=</span> <span class="s">"Les Paul"</span><span class="o">;</span>
<span class="nc">StringTemplate</span> <span class="n">template</span> <span class="o">=</span> <span class="no">RAW</span><span class="o">.</span><span class="s">"I bought a \{guitarType} yesterday."</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">STR</span><span class="o">.</span><span class="na">process</span><span class="o">(</span><span class="n">template</span><span class="o">));</span>
</code></pre></div></div>

<p>Template expressions are designed to prevent the direct conversion of strings with embedded expressions to interpolated strings, making it impossible for potentially incorrect strings to spread. A template processor securely handles this interpolation, and if you forget to use one, the compiler will report an error.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">guitarType</span> <span class="o">=</span> <span class="s">"Les Paul"</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"I bought a \{guitarType} yesterday."</span><span class="o">);</span> <span class="c1">// doesn't compile!</span>
<span class="c1">// outputs: "error: processor missing from template expression"</span>
</code></pre></div></div>

<h4 id="custom-template-processors">Custom Template Processors</h4>

<p>Each template processor is an object that implements the functional interface <code class="language-plaintext highlighter-rouge">StringTemplate.Processor</code>, which means developers can easily create custom template processors. Custom template processors can make use of the methods <code class="language-plaintext highlighter-rouge">StringTemplate::fragments</code> and <code class="language-plaintext highlighter-rouge">StringTemplate::values</code> in order to use static fragments and dynamic values of the string template, respectively.</p>

<p>Custom template processors can be useful for various use cases. Let’s illustrate two of them with some code examples:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="no">JSON</span> <span class="o">=</span> <span class="nc">StringTemplate</span><span class="o">.</span><span class="na">Processor</span><span class="o">.</span><span class="na">of</span><span class="o">(</span>
    <span class="o">(</span><span class="nc">StringTemplate</span> <span class="n">st</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nc">JSONObject</span><span class="o">(</span><span class="n">st</span><span class="o">.</span><span class="na">interpolate</span><span class="o">())</span>
<span class="o">);</span>

<span class="nc">String</span> <span class="n">name</span> <span class="o">=</span> <span class="s">"Gibson Les Paul Standard '50s Heritage Cherry Sunburst"</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">type</span> <span class="o">=</span> <span class="s">"Les Paul"</span><span class="o">;</span>
<span class="nc">JSONObject</span> <span class="n">doc</span> <span class="o">=</span> <span class="no">JSON</span><span class="o">.</span><span class="s">"""
    {
        "</span><span class="n">name</span><span class="s">": "</span><span class="err">\</span><span class="o">{</span><span class="n">name</span><span class="o">}</span><span class="s">",
        "</span><span class="n">type</span><span class="s">": "</span><span class="err">\</span><span class="o">{</span><span class="n">type</span><span class="o">}</span><span class="s">"
    };
    """</span><span class="o">;</span>
</code></pre></div></div>

<p>So the <code class="language-plaintext highlighter-rouge">JSON</code> template processor returns instances of <code class="language-plaintext highlighter-rouge">JSONObject</code> instead of <code class="language-plaintext highlighter-rouge">String</code>.
If we wanted, we could simply add more validation logic to the implementation of <code class="language-plaintext highlighter-rouge">JSON</code> to make the template processor handle its parameters a bit more safely.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">record</span> <span class="nf">QueryBuilder</span><span class="o">(</span><span class="nc">Connection</span> <span class="n">conn</span><span class="o">)</span> <span class="kd">implements</span> <span class="nc">StringTemplate</span><span class="o">.</span><span class="na">Processor</span><span class="o">&lt;</span><span class="nc">PreparedStatement</span><span class="o">,</span> <span class="nc">SQLException</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="nc">PreparedStatement</span> <span class="nf">process</span><span class="o">(</span><span class="nc">StringTemplate</span> <span class="n">st</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">SQLException</span> <span class="o">{</span>
        <span class="c1">// 1. Replace StringTemplate placeholders with PreparedStatement placeholders</span>
        <span class="nc">String</span> <span class="n">query</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">join</span><span class="o">(</span><span class="s">"?"</span><span class="o">,</span> <span class="n">st</span><span class="o">.</span><span class="na">fragments</span><span class="o">());</span>

        <span class="c1">// 2. Create the PreparedStatement on the connection</span>
        <span class="nc">PreparedStatement</span> <span class="n">ps</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="na">prepareStatement</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>

        <span class="c1">// 3. Set parameters of the PreparedStatement</span>
        <span class="kt">int</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
        <span class="k">for</span> <span class="o">(</span><span class="nc">Object</span> <span class="n">value</span> <span class="o">:</span> <span class="n">st</span><span class="o">.</span><span class="na">values</span><span class="o">())</span> <span class="o">{</span>
            <span class="k">switch</span> <span class="o">(</span><span class="n">value</span><span class="o">)</span> <span class="o">{</span>
                <span class="k">case</span> <span class="nc">Integer</span> <span class="n">i</span> <span class="o">-&gt;</span> <span class="n">ps</span><span class="o">.</span><span class="na">setInt</span><span class="o">(</span><span class="n">index</span><span class="o">++,</span> <span class="n">i</span><span class="o">);</span>
                <span class="k">case</span> <span class="nc">Float</span> <span class="n">f</span>   <span class="o">-&gt;</span> <span class="n">ps</span><span class="o">.</span><span class="na">setFloat</span><span class="o">(</span><span class="n">index</span><span class="o">++,</span> <span class="n">f</span><span class="o">);</span>
                <span class="k">case</span> <span class="nc">Double</span> <span class="n">d</span>  <span class="o">-&gt;</span> <span class="n">ps</span><span class="o">.</span><span class="na">setDouble</span><span class="o">(</span><span class="n">index</span><span class="o">++,</span> <span class="n">d</span><span class="o">);</span>
                <span class="k">case</span> <span class="nc">Boolean</span> <span class="n">b</span> <span class="o">-&gt;</span> <span class="n">ps</span><span class="o">.</span><span class="na">setBoolean</span><span class="o">(</span><span class="n">index</span><span class="o">++,</span> <span class="n">b</span><span class="o">);</span>
                <span class="k">default</span>        <span class="o">-&gt;</span> <span class="n">ps</span><span class="o">.</span><span class="na">setString</span><span class="o">(</span><span class="n">index</span><span class="o">++,</span> <span class="nc">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="n">value</span><span class="o">));</span>
            <span class="o">}</span>
        <span class="o">}</span>

        <span class="k">return</span> <span class="n">ps</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="no">DB</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">QueryBuilder</span><span class="o">(</span><span class="n">conn</span><span class="o">);</span>
<span class="nc">String</span> <span class="n">type</span> <span class="o">=</span> <span class="s">"Les Paul"</span><span class="o">;</span> 
<span class="nc">PreparedStatement</span> <span class="n">ps</span> <span class="o">=</span> <span class="no">DB</span><span class="o">.</span><span class="s">"SELECT * FROM Guitar g WHERE g.guitar_type = \{type}"</span><span class="o">;</span>
<span class="nc">ResultSet</span> <span class="n">rs</span> <span class="o">=</span> <span class="n">ps</span><span class="o">.</span><span class="na">executeQuery</span><span class="o">();</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">DB</code> custom template processor is capable of constructing <code class="language-plaintext highlighter-rouge">PreparedStatements</code> that have their parameters injected in a safe way.</p>

<h4 id="whats-different-from-java-21-2">What’s Different From Java 21?</h4>

<p>Except for a technical change in template expression types, there are no changes relative to the first preview.</p>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-2">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/459">JEP 459</a>.</p>

<h3 id="jep-463-implicitly-declared-classes-and-instance-main-methods-second-preview">JEP 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)</h3>

<p>Java’s take on the classic <a href="https://en.wikipedia.org/wiki/%22Hello,_World!%22_program">Hello, World!</a> program is notoriously verbose:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="o">{</span> 
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span> 
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello, World!"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>On top of that, it forces newcomers to grasp a few concepts that they certainly don’t need on their first day of Java programming:</p>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">public</code> access modifier and its role in encapsulating units of code, together with its counterparts <code class="language-plaintext highlighter-rouge">private</code>, <code class="language-plaintext highlighter-rouge">protected</code> and default;</li>
  <li>The <code class="language-plaintext highlighter-rouge">String[] args</code> parameter, that allows the operating system’s shell to pass arguments to the program;</li>
  <li>The <code class="language-plaintext highlighter-rouge">static</code> modifier and how it’s part of Java’s class-and-object model.</li>
</ul>

<p>The motivation for this JEP is to help programmers that are new to Java by introducing concepts in the right order, starting with the more fundamental ones. This is done by hiding any unnecessary details until they are useful in larger programs.</p>

<h4 id="changing-the-launch-protocol">Changing the Launch Protocol</h4>

<p>To achieve this, the JEP proposes the following changes to the launch protocol:</p>

<ul>
  <li>allow <em>instance main methods</em>, which are not <code class="language-plaintext highlighter-rouge">static</code> and don’t need a <code class="language-plaintext highlighter-rouge">public</code> modifier, nor a <code class="language-plaintext highlighter-rouge">String[]</code> parameter;</li>
</ul>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="o">{</span> 
    <span class="kt">void</span> <span class="nf">main</span><span class="o">()</span> <span class="o">{</span> <span class="c1">// this is an instance main method</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello, World!"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<ul>
  <li>allow a compilation unit to implicitly declare a class:</li>
</ul>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">main</span><span class="o">()</span> <span class="o">{</span> <span class="c1">// this is an instance main method in an implicitly declared class</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello, World!"</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<h4 id="a-flexible-launch-protocol">A flexible launch protocol</h4>

<p>Java 22 enhances the launch protocol even further to offer more flexibility in declaring a program’s entry point. The <code class="language-plaintext highlighter-rouge">main</code> method of a launched class can now have <code class="language-plaintext highlighter-rouge">public</code>, <code class="language-plaintext highlighter-rouge">protected</code> or default access. Other enhancements of the launch protocol include:</p>

<ul>
  <li>If the launched class contains a main method with a <code class="language-plaintext highlighter-rouge">String[]</code> parameter, then choose that method.</li>
  <li>Otherwise, if the class contains a main method with no parameters, then choose that method.</li>
  <li>In either case, if the chosen method is <code class="language-plaintext highlighter-rouge">static</code>, then simply invoke it.</li>
  <li>Otherwise, the chosen method is an instance method and the launched class must have a zero-parameter, non-private constructor. Invoke that constructor and then invoke the <code class="language-plaintext highlighter-rouge">main</code> method of the resulting object. If there is no such constructor, then report an error and terminate.</li>
  <li>If there is no suitable <code class="language-plaintext highlighter-rouge">main</code> method, then report an error and terminate.</li>
</ul>

<h4 id="implicitly-declared-classes">Implicitly Declared Classes</h4>

<p>With the introduction of implicitly declared classes, the Java compiler will consider a method that is not enclosed in a class declaration, as well as any unenclosed fields and any classes declared in the file, to be members of an implicitly declared top-level class. 
Such a class always belongs to the unnamed package, is <code class="language-plaintext highlighter-rouge">final</code>, and can’t implement interfaces or extend classes except <code class="language-plaintext highlighter-rouge">Object</code>. You can’t reference it by name or use method references for its static methods, but you can use <code class="language-plaintext highlighter-rouge">this</code> and make method references to its instance methods. Implicitly declared classes can’t be instantiated or referenced by name in code. They’re mainly used as program entry points and must have a <code class="language-plaintext highlighter-rouge">main</code> method, enforced by the Java compiler.</p>

<h4 id="whats-different-from-java-21-3">What’s Different From Java 21?</h4>

<p>Java 22 contains the following changes compared to Java 21:</p>

<ul>
  <li>The feature that is now called <em>implicitly declared classes</em> used to be called <em>unnamed classes</em>. The latter came with a mechanism to prevent an unnamed class being used by other classes. In contrast, implicitly declared classes use a simpler approach: a source file without an enclosing class declaration is said to implicitly declare a class with a name chosen by the host system. These classes behave like normal top-level classes and require no additional tooling, library, or runtime support.</li>
  <li>The procedure for selecting a main method to invoke was too complicated, taking into account both whether the method had a parameter and whether it was a static or an instance method. Java 22 simplifies the selection process to two steps: If there is a candidate <code class="language-plaintext highlighter-rouge">main</code> method with a <code class="language-plaintext highlighter-rouge">String[]</code> parameter, then we invoke that method; otherwise we invoke a candidate <code class="language-plaintext highlighter-rouge">main</code> method with no parameters. There is no ambiguity here, because a class cannot declare a static method and an instance method of the same name and signature.</li>
</ul>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-3">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/463">JEP 463</a>.</p>

<h2 id="from-project-loom">From Project Loom</h2>

<p>Java 22 contains two features that originated from <a href="http://openjdk.java.net/projects/loom/">Project Loom</a>:</p>

<ul>
  <li>Structured Concurrency</li>
  <li>Scoped Values</li>
</ul>

<blockquote>
  <p>Project Loom strives to simplify maintaining concurrent applications in Java by introducing <em>virtual threads</em> and an API for <em>structured concurrency</em>, among other things.</p>
</blockquote>

<h3 id="jep-462-structured-concurrency-second-preview">JEP 462: Structured Concurrency (Second Preview)</h3>

<p>Java’s take on concurrency has always been <em>unstructured</em>, meaning that tasks run independently of each other. There’s no hierarchy, scope, or other structure involved, which means errors or cancellation intent is hard to communicate.
To illustrate this, let’s look at a code example that takes place in a restaurant:</p>

<blockquote>
  <p>The code examples that illustrate Structured Concurrency were taken from my conference talk <a href="https://hanno.codes/talks/#javas-concurrency-journey-continues">“Java’s Concurrency Journey Continues! Exploring Structured Concurrency and Scoped Values”</a>.</p>
</blockquote>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">MultiWaiterRestaurant</span> <span class="kd">implements</span> <span class="nc">Restaurant</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">MultiCourseMeal</span> <span class="nf">announceMenu</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">ExecutionException</span><span class="o">,</span> <span class="nc">InterruptedException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">grover</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Grover"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">rosita</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Rosita"</span><span class="o">);</span>

        <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">executor</span> <span class="o">=</span> <span class="nc">Executors</span><span class="o">.</span><span class="na">newVirtualThreadPerTaskExecutor</span><span class="o">())</span> <span class="o">{</span>
            <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">starter</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">grover</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">STARTER</span><span class="o">));</span>
            <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">main</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">MAIN</span><span class="o">));</span>
            <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">dessert</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">rosita</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">DESSERT</span><span class="o">));</span>

            <span class="k">return</span> <span class="k">new</span> <span class="nf">MultiCourseMeal</span><span class="o">(</span><span class="n">starter</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">main</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">dessert</span><span class="o">.</span><span class="na">get</span><span class="o">());</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Note that the <code class="language-plaintext highlighter-rouge">announceCourse(..)</code> method in the <code class="language-plaintext highlighter-rouge">Waiter</code> class sometimes fails with an <code class="language-plaintext highlighter-rouge">OutOfStockException</code>, because one of the ingredients for the course might not be in stock. This can lead to some problems:</p>

<ul>
  <li>If <code class="language-plaintext highlighter-rouge">zoe.announceCourse(CourseType.MAIN)</code> takes a long time to execute but <code class="language-plaintext highlighter-rouge">grover.announceCourse(CourseType.STARTER)</code> fails in the meantime, the <code class="language-plaintext highlighter-rouge">announceMenu(..)</code> method will unnecessarily wait for the main course announcement by blocking on <code class="language-plaintext highlighter-rouge">main.get()</code>, instead of cancelling it (which would be the sensible thing to do).</li>
  <li>If an exception happens in <code class="language-plaintext highlighter-rouge">zoe.announceCourse(CourseType.MAIN)</code>, <code class="language-plaintext highlighter-rouge">main.get()</code> will throw it, but <code class="language-plaintext highlighter-rouge">grover.announceCourse(CourseType.STARTER)</code> will continue to run in its own thread, resulting in thread leakage.</li>
  <li>If the thread executing <code class="language-plaintext highlighter-rouge">announceMenu(..)</code> is interrupted, the interruption will not propagate to the subtasks: all threads that run an <code class="language-plaintext highlighter-rouge">announceCourse(..)</code> invocation will leak, continuing to run even after <code class="language-plaintext highlighter-rouge">announceMenu()</code> has failed.</li>
</ul>

<p>Ultimately the problem here is that our program is logically structured with task-subtask relationships, but these relationships exist only in the mind of the developer. We might all prefer structured code that reads like a sequential story, but this example simply doesn’t meet that criterion.</p>

<p>In contrast, the execution of single-threaded code <em>always</em> enforces a hierarchy of tasks and subtasks, as shown by the single-threaded version of our restaurant example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">SingleWaiterRestaurant</span> <span class="kd">implements</span> <span class="nc">Restaurant</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">MultiCourseMeal</span> <span class="nf">announceMenu</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">OutOfStockException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">elmo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Elmo"</span><span class="o">);</span>

        <span class="nc">Course</span> <span class="n">starter</span> <span class="o">=</span> <span class="n">elmo</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">STARTER</span><span class="o">);</span>
        <span class="nc">Course</span> <span class="n">main</span> <span class="o">=</span> <span class="n">elmo</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">MAIN</span><span class="o">);</span>
        <span class="nc">Course</span> <span class="n">dessert</span> <span class="o">=</span> <span class="n">elmo</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">DESSERT</span><span class="o">);</span>

        <span class="k">return</span> <span class="k">new</span> <span class="nf">MultiCourseMeal</span><span class="o">(</span><span class="n">starter</span><span class="o">,</span> <span class="n">main</span><span class="o">,</span> <span class="n">dessert</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here, we don’t have <em>any</em> of the problems we had before.
Our waiter Elmo will announce the courses in exactly the right order, and if one subtask fails the remaining one(s) won’t even be started.
And because all work runs in the same thread, there is no risk of thread leakage.</p>

<p>It became apparent from these examples that concurrent programming would be a lot easier and more intuitive if enforcing the hierarchy of tasks and subtasks was possible, just like with single-threaded code.</p>

<h4 id="introducing-structured-concurrency">Introducing Structured Concurrency</h4>

<p>In a structured concurrency approach, threads have a clear hierarchy, their own scope, and clear entry and exit points. Structured concurrency arranges threads hierarchically, akin to function calls, forming a tree with parent-child relationships. Execution scopes persist until all child threads complete, matching code structure.</p>

<h4 id="shutdown-on-failure">Shutdown on Failure</h4>

<p>Let’s now take a look at a structured, concurrent version of our example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">StructuredConcurrencyRestaurant</span> <span class="kd">implements</span> <span class="nc">Restaurant</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">MultiCourseMeal</span> <span class="nf">announceMenu</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">ExecutionException</span><span class="o">,</span> <span class="nc">InterruptedException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">grover</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Grover"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">rosita</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Rosita"</span><span class="o">);</span>

        <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">scope</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StructuredTaskScope</span><span class="o">.</span><span class="na">ShutdownOnFailure</span><span class="o">())</span> <span class="o">{</span>
            <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">starter</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">grover</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">STARTER</span><span class="o">));</span>
            <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">main</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">MAIN</span><span class="o">));</span>
            <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">dessert</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">rosita</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">DESSERT</span><span class="o">));</span>

            <span class="n">scope</span><span class="o">.</span><span class="na">join</span><span class="o">();</span> <span class="c1">// 1</span>
            <span class="n">scope</span><span class="o">.</span><span class="na">throwIfFailed</span><span class="o">();</span> <span class="c1">// 2</span>

            <span class="k">return</span> <span class="k">new</span> <span class="nf">MultiCourseMeal</span><span class="o">(</span><span class="n">starter</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">main</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">dessert</span><span class="o">.</span><span class="na">get</span><span class="o">());</span> <span class="c1">// 3</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>The scope’s purpose is to keep the threads together.
At <code class="language-plaintext highlighter-rouge">1</code>, we wait (<code class="language-plaintext highlighter-rouge">join</code>) until <em>all</em> threads are done with their work. 
If one of the threads is interrupted, an <code class="language-plaintext highlighter-rouge">InterruptedException</code> is thrown here. 
At <code class="language-plaintext highlighter-rouge">2</code>, an <code class="language-plaintext highlighter-rouge">ExecutionException</code> is thrown if an exception occurs in one of the threads. 
Once we reach <code class="language-plaintext highlighter-rouge">3</code>, we can be sure everything has gone well, and we can retrieve and process the results.</p>

<p>Actually, the main difference with the code we had before is the fact that we create threads (<code class="language-plaintext highlighter-rouge">fork</code>) within a new <code class="language-plaintext highlighter-rouge">scope</code>. 
Now we can be certain that the lifetimes of the three threads are confined to this scope, which coincides with the body of the try-with-resources statement.</p>

<p>Furthermore, we’ve gained <em>short-circuiting behaviour</em>. 
When one of the <code class="language-plaintext highlighter-rouge">announceCourse(..)</code> subtasks fails, the others are cancelled if they didn’t complete yet.
This behaviour is managed by the <code class="language-plaintext highlighter-rouge">ShutdownOnFailure</code> policy.
We’ve also gained <em>cancellation propagation</em>.
When the thread that runs <code class="language-plaintext highlighter-rouge">announceMenu()</code> is interrupted before or during the call to <code class="language-plaintext highlighter-rouge">scope.join()</code>, all subtasks are cancelled automatically when the thread exits the scope.</p>

<h4 id="shutdown-on-success">Shutdown on Success</h4>

<p>A shutdown-on-failure policy cancels tasks if one of them fails, while a <em>shutdown-on-success</em> policy cancels tasks if one succeeds. The latter is useful to prevent unnecessary work once a successful result is obtained.</p>

<p>Let’s see what a shutdown-on-success implementation would look like:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="n">record</span> <span class="nf">DrinkOrder</span><span class="o">(</span><span class="nc">Guest</span> <span class="n">guest</span><span class="o">,</span> <span class="nc">Drink</span> <span class="n">drink</span><span class="o">)</span> <span class="o">{}</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">StructuredConcurrencyBar</span> <span class="kd">implements</span> <span class="nc">Bar</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">DrinkOrder</span> <span class="nf">determineDrinkOrder</span><span class="o">(</span><span class="nc">Guest</span> <span class="n">guest</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">InterruptedException</span><span class="o">,</span> <span class="nc">ExecutionException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">elmo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Elmo"</span><span class="o">);</span>

        <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">scope</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StructuredTaskScope</span><span class="o">.</span><span class="na">ShutdownOnSuccess</span><span class="o">&lt;</span><span class="nc">DrinkOrder</span><span class="o">&gt;())</span> <span class="o">{</span>
            <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">getDrinkOrder</span><span class="o">(</span><span class="n">guest</span><span class="o">,</span> <span class="no">BEER</span><span class="o">,</span> <span class="no">WINE</span><span class="o">,</span> <span class="no">JUICE</span><span class="o">));</span>
            <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">elmo</span><span class="o">.</span><span class="na">getDrinkOrder</span><span class="o">(</span><span class="n">guest</span><span class="o">,</span> <span class="no">COFFEE</span><span class="o">,</span> <span class="no">TEA</span><span class="o">,</span> <span class="no">COCKTAIL</span><span class="o">,</span> <span class="no">DISTILLED</span><span class="o">));</span>

            <span class="k">return</span> <span class="n">scope</span><span class="o">.</span><span class="na">join</span><span class="o">().</span><span class="na">result</span><span class="o">();</span> <span class="c1">// 1</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>In this example the waiter is responsible for getting a valid <code class="language-plaintext highlighter-rouge">DrinkOrder</code> object based on guest preference and the drinks supply at the bar.
In the method <code class="language-plaintext highlighter-rouge">Waiter.getDrinkOrder(Guest guest, DrinkCategory... categories)</code>, the waiter starts to list all available drinks in the drink categories that were passed to the method.
Once a guest hears something they like, they respond and the waiter creates a drink order. When this happens, the <code class="language-plaintext highlighter-rouge">getDrinkOrder(..)</code> method returns a <code class="language-plaintext highlighter-rouge">DrinkOrder</code> object and the scope will shut down. 
This means that any unfinished subtasks (such as the one in which Elmo is still listing different kinds of tea) will be cancelled.
The <code class="language-plaintext highlighter-rouge">result()</code> method at <code class="language-plaintext highlighter-rouge">1</code> will either return a valid <code class="language-plaintext highlighter-rouge">DrinkOrder</code> object, or throw an <code class="language-plaintext highlighter-rouge">ExecutionException</code> if one of the subtasks has failed.</p>

<h4 id="custom-shutdown-policies">Custom Shutdown Policies</h4>

<p>Two shutdown policies are provided out-of-the-box, but it’s also possible to create your own by extending the class <code class="language-plaintext highlighter-rouge">StructuredTaskScope</code> and its protected <code class="language-plaintext highlighter-rouge">handleComplete(..)</code> method.
That will allow you to have full control over when the scope will shut down and what results will be collected.</p>

<h4 id="whats-different-from-java-21-4">What’s Different From Java 21?</h4>

<p>Compared to the preview version of this feature in Java 21, nothing was changed or added. JEP 462 simply exists to gather more feedback from users.</p>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-4">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/462">JEP 462</a>.</p>

<h3 id="jep-464-scoped-values-second-preview">JEP 464: Scoped Values (Second Preview)</h3>

<p><em>Scoped values</em> 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.</p>

<blockquote>
  <p>The code examples that illustrate Scoped Values were taken from my conference talk <a href="https://hanno.codes/talks/#javas-concurrency-journey-continues">“Java’s Concurrency Journey Continues! Exploring Structured Concurrency and Scoped Values”</a>.</p>
</blockquote>

<h4 id="threadlocal">ThreadLocal</h4>

<p>Since Java 1.2 we can make use of <code class="language-plaintext highlighter-rouge">ThreadLocal</code> variables, which confine a certain value to the thread that created it. Back then this was a simple way to achieve thread-safety, <a href="https://stackoverflow.com/a/817926">in some cases</a>.</p>

<p>But thread-local variables also come with a few caveats. Every thread-local variable is mutable, making it hard to discern where shared state is updated and in what order. There’s also the risk of memory leaks, because unless you call <code class="language-plaintext highlighter-rouge">remove()</code> on the <code class="language-plaintext highlighter-rouge">ThreadLocal</code> the data is retained until it is garbage collected (which is only after the thread terminates). And finally, thread-local variables of a parent thread can be inherited by child threads, meaning that the child thread has to allocate storage for every thread-local variable previously written in the parent thread.</p>

<p>These drawbacks become more apparent now that virtual threads have been introduced, because millions of them could be active at the same time - each with their own thread-local variables - resulting in a significant memory footprint.</p>

<h4 id="scoped-values">Scoped Values</h4>

<p>Like a thread-local variable, a scoped value has multiple incarnations, one per thread. Unlike a thread-local variable, a scoped value is written once and is then immutable. It’s available only for a bounded period during execution of the thread.</p>

<p>To demonstrate this feature, we’ve added a scoped value to the <code class="language-plaintext highlighter-rouge">StructuredConcurrencyBar</code> class that you’re already familiar with:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">StructuredConcurrencyBar</span> <span class="kd">implements</span> <span class="nc">Bar</span> <span class="o">{</span>
    <span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="nc">ScopedValue</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">drinkOrderId</span> <span class="o">=</span> <span class="nc">ScopedValue</span><span class="o">.</span><span class="na">newInstance</span><span class="o">();</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">DrinkOrder</span> <span class="nf">determineDrinkOrder</span><span class="o">(</span><span class="nc">Guest</span> <span class="n">guest</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">elmo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Elmo"</span><span class="o">);</span>

        <span class="k">return</span> <span class="nc">ScopedValue</span><span class="o">.</span><span class="na">where</span><span class="o">(</span><span class="n">drinkOrderId</span><span class="o">,</span> <span class="mi">1</span><span class="o">)</span>
                <span class="o">.</span><span class="na">call</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="o">{</span>
                    <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">scope</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StructuredTaskScope</span><span class="o">.</span><span class="na">ShutdownOnSuccess</span><span class="o">&lt;</span><span class="nc">DrinkOrder</span><span class="o">&gt;())</span> <span class="o">{</span>
                        <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">getDrinkOrder</span><span class="o">(</span><span class="n">guest</span><span class="o">,</span> <span class="no">BEER</span><span class="o">,</span> <span class="no">WINE</span><span class="o">,</span> <span class="no">JUICE</span><span class="o">));</span>
                        <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">elmo</span><span class="o">.</span><span class="na">getDrinkOrder</span><span class="o">(</span><span class="n">guest</span><span class="o">,</span> <span class="no">COFFEE</span><span class="o">,</span> <span class="no">TEA</span><span class="o">,</span> <span class="no">COCKTAIL</span><span class="o">,</span> <span class="no">DISTILLED</span><span class="o">));</span>

                        <span class="k">return</span> <span class="n">scope</span><span class="o">.</span><span class="na">join</span><span class="o">().</span><span class="na">result</span><span class="o">();</span>
                    <span class="o">}</span>
                <span class="o">});</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>We see that <code class="language-plaintext highlighter-rouge">ScopedValue.where(...)</code> is called, presenting a scoped value and the object to which it is to be bound. The invocation of <code class="language-plaintext highlighter-rouge">call(...)</code> binds the scoped value, providing an incarnation that is specific to the current thread, and then executes the lambda expression passed as argument. During the lifetime of <code class="language-plaintext highlighter-rouge">call(...)</code>, the lambda expression - and any method called (in)directly from it - can read the scoped value via the value’s <code class="language-plaintext highlighter-rouge">get()</code> method. After the <code class="language-plaintext highlighter-rouge">call(...)</code> method finishes, the binding is destroyed.</p>

<h4 id="typical-use-cases">Typical Use Cases</h4>

<p>Scoped values will be useful in all places where currently thread-local variables are used for the purpose of one-way transmission of unchanging data.</p>

<h4 id="whats-different-from-java-21-5">What’s Different From Java 21?</h4>

<p>Compared to the preview version of this feature in Java 21, nothing was changed or added. JEP 464 simply exists to gather more feedback from users of this feature.</p>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-5">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/464">JEP 464</a>.</p>

<h2 id="from-project-panama">From Project Panama</h2>

<p>Java 22 contains two features that originated from <a href="http://openjdk.java.net/projects/panama/">Project Panama</a>:</p>

<ul>
  <li>Foreign Function &amp; Memory API</li>
  <li>Vector API</li>
</ul>

<blockquote>
  <p>Project Panama aims to improve the connection between the JVM and foreign (non-Java) libraries.</p>
</blockquote>

<h3 id="jep-454-foreign-function--memory-api">JEP 454: Foreign Function &amp; Memory API</h3>

<p>Java programs have always had the option of interacting with code and data outside of the Java runtime, through the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jni/">Java Native Interface</a> (JNI).
And accessing foreign memory (outside of the JVM, so off-heap) was possible using either the <a href="https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/nio/ByteBuffer.html">ByteBuffer API</a> or the <a href="https://github.com/openjdk/jdk/blob/master/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java">sun.misc.Unsafe API</a>.</p>

<p>However, these mechanisms have downsides, which is why a more modern API is now proposed to support foreign functions and foreign memory in a better way.</p>

<blockquote>
  <p>Performance-critical libraries like <a href="https://github.com/tensorflow/tensorflow">Tensorflow</a>, <a href="https://lucene.apache.org/">Lucene</a> or <a href="https://netty.io/">Netty</a> typically rely on using foreign memory, because they need more control over the memory they use to prevent the cost and unpredictability that comes with garbage collection.</p>
</blockquote>

<h4 id="code-example">Code Example</h4>

<p><a href="https://openjdk.org/jeps/454">JEP 454</a> lists a code example that obtains a method handle for the C library function <code class="language-plaintext highlighter-rouge">radixsort</code> and then uses it to sort four strings that start out as Java array elements:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// 1. Find foreign function on the C library path</span>
<span class="nc">Linker</span> <span class="n">linker</span>          <span class="o">=</span> <span class="nc">Linker</span><span class="o">.</span><span class="na">nativeLinker</span><span class="o">();</span>
<span class="nc">SymbolLookup</span> <span class="n">stdlib</span>    <span class="o">=</span> <span class="n">linker</span><span class="o">.</span><span class="na">defaultLookup</span><span class="o">();</span>
<span class="nc">MethodHandle</span> <span class="n">radixsort</span> <span class="o">=</span> <span class="n">linker</span><span class="o">.</span><span class="na">downcallHandle</span><span class="o">(</span><span class="n">stdlib</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="s">"radixsort"</span><span class="o">),</span> <span class="o">...);</span>
<span class="c1">// 2. Allocate on-heap memory to store four strings</span>
<span class="nc">String</span><span class="o">[]</span> <span class="n">javaStrings</span> <span class="o">=</span> <span class="o">{</span> <span class="s">"mouse"</span><span class="o">,</span> <span class="s">"cat"</span><span class="o">,</span> <span class="s">"dog"</span><span class="o">,</span> <span class="s">"car"</span> <span class="o">};</span>
<span class="c1">// 3. Use try-with-resources to manage the lifetime of off-heap memory</span>
<span class="k">try</span> <span class="o">(</span><span class="nc">Arena</span> <span class="n">offHeap</span> <span class="o">=</span> <span class="nc">Arena</span><span class="o">.</span><span class="na">ofConfined</span><span class="o">())</span> <span class="o">{</span>
    <span class="c1">// 4. Allocate a region of off-heap memory to store four pointers</span>
    <span class="nc">MemorySegment</span> <span class="n">pointers</span>
        <span class="o">=</span> <span class="n">offHeap</span><span class="o">.</span><span class="na">allocate</span><span class="o">(</span><span class="nc">ValueLayout</span><span class="o">.</span><span class="na">ADDRESS</span><span class="o">,</span> <span class="n">javaStrings</span><span class="o">.</span><span class="na">length</span><span class="o">);</span>
    <span class="c1">// 5. Copy the strings from on-heap to off-heap</span>
    <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">javaStrings</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="nc">MemorySegment</span> <span class="n">cString</span> <span class="o">=</span> <span class="n">offHeap</span><span class="o">.</span><span class="na">allocateFrom</span><span class="o">(</span><span class="n">javaStrings</span><span class="o">[</span><span class="n">i</span><span class="o">]);</span>
        <span class="n">pointers</span><span class="o">.</span><span class="na">setAtIndex</span><span class="o">(</span><span class="nc">ValueLayout</span><span class="o">.</span><span class="na">ADDRESS</span><span class="o">,</span> <span class="n">i</span><span class="o">,</span> <span class="n">cString</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="c1">// 6. Sort the off-heap data by calling the foreign function</span>
    <span class="n">radixsort</span><span class="o">.</span><span class="na">invoke</span><span class="o">(</span><span class="n">pointers</span><span class="o">,</span> <span class="n">javaStrings</span><span class="o">.</span><span class="na">length</span><span class="o">,</span> <span class="nc">MemorySegment</span><span class="o">.</span><span class="na">NULL</span><span class="o">,</span> <span class="sc">'\0'</span><span class="o">);</span>
    <span class="c1">// 7. Copy the (reordered) strings from off-heap to on-heap</span>
    <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">javaStrings</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="nc">MemorySegment</span> <span class="n">cString</span> <span class="o">=</span> <span class="n">pointers</span><span class="o">.</span><span class="na">getAtIndex</span><span class="o">(</span><span class="nc">ValueLayout</span><span class="o">.</span><span class="na">ADDRESS</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
        <span class="n">javaStrings</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="n">cString</span><span class="o">.</span><span class="na">reinterpret</span><span class="o">(...).</span><span class="na">getString</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span> <span class="c1">// 8. All off-heap memory is deallocated here</span>
<span class="k">assert</span> <span class="nc">Arrays</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">javaStrings</span><span class="o">,</span> <span class="k">new</span> <span class="nc">String</span><span class="o">[]</span> <span class="o">{</span><span class="s">"car"</span><span class="o">,</span> <span class="s">"cat"</span><span class="o">,</span> <span class="s">"dog"</span><span class="o">,</span> <span class="s">"mouse"</span><span class="o">});</span>  <span class="c1">// true</span>
</code></pre></div></div>

<p>Let’s look at some of the types this code uses in more detail to get a rough idea of their function and purpose within the Foreign Function &amp; Memory API:</p>

<dl>
  <dt><code class="language-plaintext highlighter-rouge">Linker</code></dt>
  <dd>Provides access to foreign functions from Java code, and access to Java code from foreign functions. It allows Java code to link against foreign functions, via <em>downcall method handles</em>. It also allows foreign functions to call Java method handles, via the generation of <em>upcall stubs</em>. See the <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/foreign/Linker.html">JavaDoc</a> of this type for more information.</dd>
  <dt><code class="language-plaintext highlighter-rouge">SymbolLookup</code></dt>
  <dd>Retrieves the address of a symbol in one or more libraries. See the <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/foreign/SymbolLookup.html">JavaDoc</a> of this type for more information.</dd>
  <dt><code class="language-plaintext highlighter-rouge">Arena</code></dt>
  <dd>Controls the lifecycle of memory segments. An arena has a scope, called the arena scope. When the arena is closed, the arena scope is no longer alive. As a result, all the segments associated with the arena scope are invalidated, their backing memory regions are deallocated (where applicable) and can no longer be accessed after the arena is closed. See the <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/foreign/Arena.html">JavaDoc</a> of this type for more information.</dd>
  <dt><code class="language-plaintext highlighter-rouge">MemorySegment</code></dt>
  <dd>Provides access to a contiguous region of memory. There are two kinds of memory segments: <em>heap segments</em> (inside the Java memory heap) and <em>native segments</em> (outside of the Java memory heap). See the <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/foreign/MemorySegment.html">JavaDoc</a> of this type for more information.</dd>
  <dt><code class="language-plaintext highlighter-rouge">ValueLayout</code></dt>
  <dd>Models values of basic data types, such as <em>integral</em> values, <em>floating-point</em> values and <em>address</em> values. On top of that, it defines useful value layout constants for Java primitive types and addresses. See the <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/foreign/ValueLayout.html">JavaDoc</a> of this type for more information.</dd>
</dl>

<h4 id="whats-different-from-java-21-6">What’s Different From Java 21?</h4>

<p>In Java 21, this feature was in third preview (in the form of <a href="https://openjdk.org/jeps/442">JEP 442</a>) to gather more developer feedback. Based on this feedback the following changes happened in Java 22:</p>

<ul>
  <li>A new linker option allowing clients to pass heap segments to downcall method handles is now provided;</li>
  <li>The Enable-Native-Access JAR-file manifest attribute has been introduced, allowing code in executable JAR files to call restricted methods without having to use the <code class="language-plaintext highlighter-rouge">--enable-native-access</code> command-line option;</li>
  <li>Clients to build C-language function descriptors programmatically have been enabled, avoiding platform-specific constants;</li>
  <li>Support for variable-length arrays in native memory has been improved;</li>
  <li>Support for arbitrary charsets for native strings has been added.</li>
</ul>

<p>On top of that, the feature has been finalized!</p>

<h4 id="more-information-6">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/454">JEP 454</a>.</p>

<h3 id="jep-460-vector-api-seventh-incubator">JEP 460: Vector API (Seventh Incubator)</h3>

<p>The Vector API makes it possible to express vector computations that reliably compile at runtime to optimal vector instructions. 
This means that these computations will significantly outperform equivalent scalar computations on the supported CPU architectures (x64 and AArch64).</p>

<h4 id="vector-computations-help-me-out-here">Vector Computations? Help Me Out Here!</h4>

<p>A <em>vector computation</em> is a mathematical operation on one or more one-dimensional matrices of an arbitrary length. Think of a vector as an array with a dynamic length. Furthermore, the elements in the vector can be accessed in constant time via indices, just like with an array.</p>

<p>In the past, Java programmers could only program such computations at the assembly-code level. But now that modern CPUs support advanced <a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">SIMD</a> features (Single Instruction, Multiple Data), it becomes more important to take advantage of the performance gains that SIMD instructions and multiple lanes operating in parallel can bring. The Vector API brings that possibility closer to the Java programmer.</p>

<h4 id="code-example-1">Code Example</h4>

<p>Here is a code example (taken from the JEP) that compares a simple scalar computation over elements of arrays with its equivalent using the Vector API:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">scalarComputation</span><span class="o">(</span><span class="kt">float</span><span class="o">[]</span> <span class="n">a</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">b</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">c</span><span class="o">)</span> <span class="o">{</span>
   <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="n">c</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">+</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">])</span> <span class="o">*</span> <span class="o">-</span><span class="mf">1.0f</span><span class="o">;</span>
   <span class="o">}</span>
<span class="o">}</span>

<span class="kd">static</span> <span class="kd">final</span> <span class="nc">VectorSpecies</span><span class="o">&lt;</span><span class="nc">Float</span><span class="o">&gt;</span> <span class="no">SPECIES</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">SPECIES_PREFERRED</span><span class="o">;</span>

<span class="kt">void</span> <span class="nf">vectorComputation</span><span class="o">(</span><span class="kt">float</span><span class="o">[]</span> <span class="n">a</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">b</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">c</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
    <span class="kt">int</span> <span class="n">upperBound</span> <span class="o">=</span> <span class="no">SPECIES</span><span class="o">.</span><span class="na">loopBound</span><span class="o">(</span><span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">);</span>
    <span class="k">for</span> <span class="o">(;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">upperBound</span><span class="o">;</span> <span class="n">i</span> <span class="o">+=</span> <span class="no">SPECIES</span><span class="o">.</span><span class="na">length</span><span class="o">())</span> <span class="o">{</span>
        <span class="c1">// FloatVector va, vb, vc;</span>
        <span class="kt">var</span> <span class="n">va</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">fromArray</span><span class="o">(</span><span class="no">SPECIES</span><span class="o">,</span> <span class="n">a</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
        <span class="kt">var</span> <span class="n">vb</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">fromArray</span><span class="o">(</span><span class="no">SPECIES</span><span class="o">,</span> <span class="n">b</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
        <span class="kt">var</span> <span class="n">vc</span> <span class="o">=</span> <span class="n">va</span><span class="o">.</span><span class="na">mul</span><span class="o">(</span><span class="n">va</span><span class="o">)</span>
                   <span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">vb</span><span class="o">.</span><span class="na">mul</span><span class="o">(</span><span class="n">vb</span><span class="o">))</span>
                   <span class="o">.</span><span class="na">neg</span><span class="o">();</span>
        <span class="n">vc</span><span class="o">.</span><span class="na">intoArray</span><span class="o">(</span><span class="n">c</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">for</span> <span class="o">(;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="n">c</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">+</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">])</span> <span class="o">*</span> <span class="o">-</span><span class="mf">1.0f</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>From the perspective of the Java developer, this is just another way of expressing scalar computations. It might come across as being more verbose, but on the other hand it can bring spectacular performance gains.</p>

<h4 id="typical-use-cases-1">Typical Use Cases</h4>

<p>The Vector API provides a way to write complex vector algorithms in Java that perform extremely well, such as vectorized <code class="language-plaintext highlighter-rouge">hashCode</code> implementations or specialized array comparisons. Numerous domains can benefit from this, including machine learning, linear algebra, encryption, text processing, finance, and code within the JDK itself.</p>

<h4 id="whats-different-from-java-21-7">What’s Different From Java 21?</h4>

<p>Aside from a minor set of bugfixes and (performance) enhancements in the API, the biggest difference with Java 21 is the support for vector access with heap <code class="language-plaintext highlighter-rouge">MemorySegment</code>s that are backed by an array of any primitive element type. Previously access was limited to heap MemorySegments backed by an array of byte.</p>

<h4 id="more-information-7">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/460">JEP 460</a>.</p>

<h2 id="hotspot">HotSpot</h2>

<p>Java 22 introduces a single change to <a href="https://openjdk.org/groups/hotspot/">HotSpot</a>:</p>

<ul>
  <li>Region Pinning for G1</li>
</ul>

<blockquote>
  <p>The HotSpot JVM is the runtime engine that is developed by Oracle. It translates Java bytecode into machine code for the host operating system’s processor architecture.</p>
</blockquote>

<h3 id="jep-423-region-pinning-for-g1">JEP 423: Region Pinning for G1</h3>

<p>The Java Native Interface (<a href="https://docs.oracle.com/en/java/javase/21/docs/specs/jni/index.html">JNI</a>) facilitates interaction between Java and unmanaged languages like C and C++. When using JNI, functions are employed to acquire and release pointers to Java objects in pairs. This creates what is called a <em>critical region</em>, where code operates on a <em>critical object</em>.</p>

<p>During garbage collection, Java must ensure that critical objects aren’t moved, as they’re being actively used. One method to achieve this is by pinning objects in place (‘region pinning’), effectively locking them during GC. However, the default garbage collector, G1, currently opts to disable GC during critical regions to avoid moving critical objects.</p>

<p>This approach can cause significant latency issues, particularly if a Java thread triggers GC while others are in critical regions. Users have reported scenarios where critical sections block application functionality for extended periods, leading to out-of-memory conditions and even VM shutdown. Consequently, some Java libraries and frameworks abstain from using critical regions to maintain throughput, despite potential adverse effects on performance.</p>

<p>JEP 423 proposes to address this issue by ensuring Java threads never wait for G1GC operations to complete, thereby mitigating the latency problems associated with critical regions.</p>

<h4 id="whats-different-from-java-21-8">What’s Different From Java 21?</h4>

<p>In Java 21, G1GC disables garbage collection during critical regions to avoid moving critical objects. In Java 22, G1GC will use <em>region pinning</em> instead.</p>

<h4 id="more-information-8">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/423">JEP 423</a>.</p>

<h2 id="compiler">Compiler</h2>

<p>Java 22 also brings us an addition that’s part of the compiler:</p>

<ul>
  <li>Launch Multi-File Source-Code Programs</li>
</ul>

<h3 id="jep-458-launch-multi-file-source-code-programs">JEP 458: Launch Multi-File Source-Code Programs</h3>

<p>Java is well-suited for building large, complex applications. But several recent additions to the JDK focus on the early stages of a software project instead, when it’s still unclear of how big it might get. Features like <a href="https://openjdk.org/jeps/222">jshell</a> and <a href="https://openjdk.org/jeps/463">instance main methods</a> come to mind, but the ability to run <code class="language-plaintext highlighter-rouge">.java</code> source files directly without an explicit compilation step (<a href="https://openjdk.org/jeps/330">JEP 330</a>) is probably the best example of Java’s current focus on starter projects.</p>

<p>A drawback of running a program like this is that all source code must be placed in a single <code class="language-plaintext highlighter-rouge">.java</code> file. To work with more than one <code class="language-plaintext highlighter-rouge">.java</code> file, a separate compilation step is still required, forcing developers to involve a build tool in their project. If the developer is still a beginner the situation is arguably worse: they must pause their learning of the language and must prioritise learning about <code class="language-plaintext highlighter-rouge">javac</code> or build tools like Maven or Gradle.</p>

<p>This is why Java 22 introduces a <code class="language-plaintext highlighter-rouge">java</code> launcher that supports running a program consisting of multiple <code class="language-plaintext highlighter-rouge">.java</code> files. Suppose a directory contains two files, <code class="language-plaintext highlighter-rouge">Prog.java</code> and <code class="language-plaintext highlighter-rouge">Helper.java</code>, where each file declares a single class:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Prog.java</span>
<span class="kd">class</span> <span class="nc">Prog</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span> <span class="nc">Helper</span><span class="o">.</span><span class="na">run</span><span class="o">();</span> <span class="o">}</span>
<span class="o">}</span>

<span class="c1">// Helper.java</span>
<span class="kd">class</span> <span class="nc">Helper</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">()</span> <span class="o">{</span> <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello!"</span><span class="o">);</span> <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Running <code class="language-plaintext highlighter-rouge">java Prog.java</code> compiles the <code class="language-plaintext highlighter-rouge">Prog</code> class in memory and executes its <code class="language-plaintext highlighter-rouge">main</code> method. If <code class="language-plaintext highlighter-rouge">Prog</code> refers to another class, such as <code class="language-plaintext highlighter-rouge">Helper</code>, the launcher locates the <code class="language-plaintext highlighter-rouge">Helper.java</code> file in the filesystem and compiles its class in memory. Furthermore, if <code class="language-plaintext highlighter-rouge">Prog.java</code> would contain a <code class="language-plaintext highlighter-rouge">Helper</code> class, then that class would be preferred over the <code class="language-plaintext highlighter-rouge">Helper</code> class in <code class="language-plaintext highlighter-rouge">Helper.java</code>; the launcher would not search for the file <code class="language-plaintext highlighter-rouge">Helper.java</code>.</p>

<h4 id="pre-compiled-classes">Pre-compiled classes</h4>

<p>You can also launch programs from the command-line that depend on libraries. Given the following directory listing…</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Prog1.java
Prog2.java
Helper.java
libs/
├─ library1.jar
├─ library2.jar
</code></pre></div></div>

<p>…we can run these programs by passing <code class="language-plaintext highlighter-rouge">--class-path lib/*</code> to the <code class="language-plaintext highlighter-rouge">java</code> launcher:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">--class-path</span> <span class="s1">'lib/*'</span> Prog1.java
<span class="nv">$ </span>java <span class="nt">--class-path</span> <span class="s1">'lib/*'</span> Prog2.java
</code></pre></div></div>
<blockquote>
  <p>The argument to the <code class="language-plaintext highlighter-rouge">--class-path</code> option is quoted to avoid expansion of the asterisk by the shell.</p>
</blockquote>

<p>The programs in this example reside in the unnamed module. If the libraries in <code class="language-plaintext highlighter-rouge">libs/</code> would be modular, we would run the programs like so:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>java <span class="nt">-p</span> lib Prog1.java
<span class="nv">$ </span>java <span class="nt">-p</span> lib Prog2.java
</code></pre></div></div>

<h4 id="whats-different-from-java-21-9">What’s Different From Java 21?</h4>

<p>Up until Java 21, running a program on the command-line directly without a separate compilation command was supported for single file programs only. Java 22 adds support for programs that span multiple files.</p>

<h4 id="more-information-9">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/458">JEP 458</a>. It contains a few more details on launch-time semantics, how the launcher finds source files and how package structure comes into play.</p>

<h2 id="core-libraries">Core Libraries</h2>

<p>Java 22 also brings you two additions that are part of the core libraries:</p>

<ul>
  <li>Class-File API</li>
  <li>Stream Gatherers</li>
</ul>

<h3 id="jep-457-class-file-api-preview">JEP 457: Class-File API (Preview)</h3>

<p>Java’s ecosystem relies heavily on the ability to parse, generate and transform class files. Frameworks use on-the-fly bytecode transformation to transparently add functionality, for example. These frameworks typically bundle class-file libraries like <a href="https://asm.ow2.io/">ASM</a> or <a href="https://www.javassist.org/">Javassist</a> to handle class file processing. However, they suffer from the fact that the six-month release cadence of the JDK causes the class-file format to evolve more quickly than before, meaning they might encounter class files that are newer than the class-file library that they bundle.</p>

<p>To solve this problem, JEP 457 proposes a standard class-file API that can produce class files that will always be up-to-date with the running JDK. This API will evolve together with the class-file format, enabling frameworks to rely solely on this API, rather than on the willingness of third-party developers to update and test their class-file libraries.</p>

<h4 id="elements-builders-and-transforms">Elements, Builders and Transforms</h4>

<p>The Class-File API, located in the <code class="language-plaintext highlighter-rouge">java.lang.classfile</code> package, consists of three main components:</p>

<dl>
  <dt><em>Elements</em></dt>
  <dd>Immutable descriptions of parts of a class file, such as instructions, attributes, fields, methods, or the entire file.</dd>
  <dt><em>Builders</em></dt>
  <dd>Corresponding builders for compound elements, offering specific building methods (e.g., <code class="language-plaintext highlighter-rouge">ClassBuilder::withMethod</code>) and serving as consumers of element types.</dd>
  <dt><em>Transforms</em></dt>
  <dd>Functions that take an element and a builder, determining if and how the element is transformed into other elements. This allows for flexible modification of class file elements.</dd>
</dl>

<h4 id="example-and-comparison-to-asm">Example and Comparison To ASM</h4>

<p>Suppose we wish to generate the following method in a class file:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">fooBar</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">z</span><span class="o">,</span> <span class="kt">int</span> <span class="n">x</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">z</span><span class="o">)</span>
        <span class="n">foo</span><span class="o">(</span><span class="n">x</span><span class="o">);</span>
    <span class="k">else</span>
        <span class="nf">bar</span><span class="o">(</span><span class="n">x</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<p>With ASM we could generate the method like so:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">ClassWriter</span> <span class="n">classWriter</span> <span class="o">=</span> <span class="o">...;</span>
<span class="nc">MethodVisitor</span> <span class="n">mv</span> <span class="o">=</span> <span class="n">classWriter</span><span class="o">.</span><span class="na">visitMethod</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="s">"fooBar"</span><span class="o">,</span> <span class="s">"(ZI)V"</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitCode</span><span class="o">();</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitVarInsn</span><span class="o">(</span><span class="no">ILOAD</span><span class="o">,</span> <span class="mi">1</span><span class="o">);</span>
<span class="nc">Label</span> <span class="n">label1</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Label</span><span class="o">();</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitJumpInsn</span><span class="o">(</span><span class="no">IFEQ</span><span class="o">,</span> <span class="n">label1</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitVarInsn</span><span class="o">(</span><span class="no">ALOAD</span><span class="o">,</span> <span class="mi">0</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitVarInsn</span><span class="o">(</span><span class="no">ILOAD</span><span class="o">,</span> <span class="mi">2</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitMethodInsn</span><span class="o">(</span><span class="no">INVOKEVIRTUAL</span><span class="o">,</span> <span class="s">"Foo"</span><span class="o">,</span> <span class="s">"foo"</span><span class="o">,</span> <span class="s">"(I)V"</span><span class="o">,</span> <span class="kc">false</span><span class="o">);</span>
<span class="nc">Label</span> <span class="n">label2</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Label</span><span class="o">();</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitJumpInsn</span><span class="o">(</span><span class="no">GOTO</span><span class="o">,</span> <span class="n">label2</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitLabel</span><span class="o">(</span><span class="n">label1</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitVarInsn</span><span class="o">(</span><span class="no">ALOAD</span><span class="o">,</span> <span class="mi">0</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitVarInsn</span><span class="o">(</span><span class="no">ILOAD</span><span class="o">,</span> <span class="mi">2</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitMethodInsn</span><span class="o">(</span><span class="no">INVOKEVIRTUAL</span><span class="o">,</span> <span class="s">"Foo"</span><span class="o">,</span> <span class="s">"bar"</span><span class="o">,</span> <span class="s">"(I)V"</span><span class="o">,</span> <span class="kc">false</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitLabel</span><span class="o">(</span><span class="n">label2</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitInsn</span><span class="o">(</span><span class="no">RETURN</span><span class="o">);</span>
<span class="n">mv</span><span class="o">.</span><span class="na">visitEnd</span><span class="o">();</span>
</code></pre></div></div>

<p>Unlike in ASM, where clients directly create a <code class="language-plaintext highlighter-rouge">ClassWriter</code> and then request a <code class="language-plaintext highlighter-rouge">MethodVisitor</code>, the Class-File API adopts a different approach. Here, instead of clients initiating a builder through a constructor or factory, they supply a lambda function that takes a builder as its parameter:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">ClassBuilder</span> <span class="n">classBuilder</span> <span class="o">=</span> <span class="o">...;</span>
<span class="n">classBuilder</span><span class="o">.</span><span class="na">withMethod</span><span class="o">(</span><span class="s">"fooBar"</span><span class="o">,</span> <span class="nc">MethodTypeDesc</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="n">CD_void</span><span class="o">,</span> <span class="n">CD_boolean</span><span class="o">,</span> <span class="n">CD_int</span><span class="o">),</span> <span class="n">flags</span><span class="o">,</span>
                        <span class="n">methodBuilder</span> <span class="o">-&gt;</span> <span class="n">methodBuilder</span><span class="o">.</span><span class="na">withCode</span><span class="o">(</span><span class="n">codeBuilder</span> <span class="o">-&gt;</span> <span class="o">{</span>
    <span class="nc">Label</span> <span class="n">label1</span> <span class="o">=</span> <span class="n">codeBuilder</span><span class="o">.</span><span class="na">newLabel</span><span class="o">();</span>
    <span class="nc">Label</span> <span class="n">label2</span> <span class="o">=</span> <span class="n">codeBuilder</span><span class="o">.</span><span class="na">newLabel</span><span class="o">();</span>
    <span class="n">codeBuilder</span><span class="o">.</span><span class="na">iload</span><span class="o">(</span><span class="mi">1</span><span class="o">)</span>
        <span class="o">.</span><span class="na">ifeq</span><span class="o">(</span><span class="n">label1</span><span class="o">)</span>
        <span class="o">.</span><span class="na">aload</span><span class="o">(</span><span class="mi">0</span><span class="o">)</span>
        <span class="o">.</span><span class="na">iload</span><span class="o">(</span><span class="mi">2</span><span class="o">)</span>
        <span class="o">.</span><span class="na">invokevirtual</span><span class="o">(</span><span class="nc">ClassDesc</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"Foo"</span><span class="o">),</span> <span class="s">"foo"</span><span class="o">,</span> <span class="nc">MethodTypeDesc</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="n">CD_void</span><span class="o">,</span> <span class="n">CD_int</span><span class="o">))</span>
        <span class="o">.</span><span class="na">goto_</span><span class="o">(</span><span class="n">label2</span><span class="o">)</span>
        <span class="o">.</span><span class="na">labelBinding</span><span class="o">(</span><span class="n">label1</span><span class="o">)</span>
        <span class="o">.</span><span class="na">aload</span><span class="o">(</span><span class="mi">0</span><span class="o">)</span>
        <span class="o">.</span><span class="na">iload</span><span class="o">(</span><span class="mi">2</span><span class="o">)</span>
        <span class="o">.</span><span class="na">invokevirtual</span><span class="o">(</span><span class="nc">ClassDesc</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"Foo"</span><span class="o">),</span> <span class="s">"bar"</span><span class="o">,</span> <span class="nc">MethodTypeDesc</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="n">CD_void</span><span class="o">,</span> <span class="n">CD_int</span><span class="o">))</span>
        <span class="o">.</span><span class="na">labelBinding</span><span class="o">(</span><span class="n">label2</span><span class="o">);</span>
        <span class="o">.</span><span class="na">return_</span><span class="o">();</span>
<span class="o">});</span>
</code></pre></div></div>

<h4 id="whats-different-from-java-21-10">What’s Different From Java 21?</h4>

<p>Starting with Java 22, frameworks will be able to rely solely on the Class-File API, rather than third party libraries like ASM or Javassist.</p>

<p>Note that the Class-File API is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-10">More Information</h4>

<p>For more information on this feature, including more details on transforming class files, see <a href="https://openjdk.org/jeps/457">JEP 457</a>.</p>

<h3 id="jep-461-stream-gatherers-preview">JEP 461: Stream Gatherers (Preview)</h3>

<p>The Stream API has been around since Java 8 and it has definitely made its way into the heart of the typical Java developer. It enables a programming style that is both efficient and expressive. Recall that a stream pipeline consists of three parts: a source of elements, any number of intermediate operations, and a terminal operation. For example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Guitar</span><span class="o">&gt;</span> <span class="n">guitars</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span>
        <span class="k">new</span> <span class="nf">Guitar</span><span class="o">(</span><span class="s">"Cordoba F7 Paco Flamenco"</span><span class="o">,</span> <span class="nc">GuitarStyle</span><span class="o">.</span><span class="na">CLASSICAL</span><span class="o">),</span>
        <span class="k">new</span> <span class="nf">Guitar</span><span class="o">(</span><span class="s">"Taylor GS Mini-e Koa"</span><span class="o">,</span> <span class="nc">GuitarStyle</span><span class="o">.</span><span class="na">WESTERN</span><span class="o">),</span>
        <span class="k">new</span> <span class="nf">Guitar</span><span class="o">(</span><span class="s">"Gibson Les Paul Standard '50s Heritage Cherry Sunburst"</span><span class="o">,</span> <span class="nc">GuitarStyle</span><span class="o">.</span><span class="na">ELECTRIC</span><span class="o">),</span>
        <span class="k">new</span> <span class="nf">Guitar</span><span class="o">(</span><span class="s">"Fender Stratocaster"</span><span class="o">,</span> <span class="nc">GuitarStyle</span><span class="o">.</span><span class="na">ELECTRIC</span><span class="o">));</span>

<span class="kt">long</span> <span class="n">numberOfNonClassicalGuitars</span> <span class="o">=</span> <span class="n">guitars</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span> <span class="c1">// source of elements</span>
        <span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">g</span> <span class="o">-&gt;</span> <span class="nc">GuitarStyle</span><span class="o">.</span><span class="na">CLASSICAL</span> <span class="o">!=</span> <span class="n">g</span><span class="o">.</span><span class="na">guitarStyle</span><span class="o">())</span> <span class="c1">// intermediate operation</span>
        <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">counting</span><span class="o">());</span> <span class="c1">// terminal operation</span>
</code></pre></div></div>

<p>The Stream API offers a relatively diverse but predetermined range of intermediate and terminal operations, including mapping, filtering, reduction, sorting, and more. Over the years, many new intermediate operations have been suggested for the Stream API. For example, it could be useful to introduce a <code class="language-plaintext highlighter-rouge">distinctBy</code> intermediate operation. A <code class="language-plaintext highlighter-rouge">distinct</code> operation <em>does</em> exist, tracking the elements it has already seen by using object equality. But what if we want distinct elements based on something else than object equality?</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">singleGuitarPerStyle</span> <span class="o">=</span> <span class="n">guitars</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
                <span class="o">.</span><span class="na">distinctBy</span><span class="o">(</span><span class="nl">Guitar:</span><span class="o">:</span><span class="n">guitarStyle</span><span class="o">)</span> <span class="c1">// hypothetical</span>
                <span class="o">.</span><span class="na">toList</span><span class="o">();</span>
</code></pre></div></div>

<p>Over the years, many new intermediate operations have been suggested for the Stream API.
Most of the suggestions that were made would make sense when considered in isolation, but adding all of them would make the (already large) Stream API more difficult to learn because its operations would be less discoverable. A better alternative would be to introduce the ability to define custom intermediate operations, analogous to how the <code class="language-plaintext highlighter-rouge">Stream::collect</code> terminal operation currently is extensible, enabling the output of a pipeline to be summarized in a variety of ways.</p>

<p>So that is why this JEP proposes an API for custom intermediate operations that allows developers to transform finite and infinite streams in their own preferred ways.</p>

<h4 id="gatherers">Gatherers</h4>

<p><code class="language-plaintext highlighter-rouge">Stream::gather(Gatherer)</code> is a new intermediate stream operation that processes stream elements by applying a user-defined <em>gatherer</em>. One could say it is the dual of <code class="language-plaintext highlighter-rouge">Stream::collect(Collector)</code>, but for intermediate operations. Gatherers transform elements in different ways: one-to-one, one-to-many, many-to-one, or many-to-many. They can track previously seen elements, enable short-circuiting for infinite streams, and support parallel execution. For example, they may start by transforming one input element into one output element but switch to transforming one input element into two output elements based on a certain condition.</p>

<p>A gatherer implements the <code class="language-plaintext highlighter-rouge">java.util.stream.Gatherer</code> interface and is defined by four functions that work together:</p>

<dl>
  <dt><em><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.html#initializer()">initializer</a></em> (optional)</dt>
  <dd>Provides an object that maintains private state while processing stream elements.</dd>
  <dt><em><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.Integrator.html">integrator</a></em></dt>
  <dd>Integrates a new element from the input stream.</dd>
  <dt><em><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.html#combiner()">combiner</a></em> (optional)</dt>
  <dd>Evaluates the gatherer in parallel when the input stream is marked as such.</dd>
  <dt><em><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.html#finisher()">finisher</a></em> (optional)</dt>
  <dd>Is invoked when there are no more input elements to consume.</dd>
</dl>

<p>When <code class="language-plaintext highlighter-rouge">Stream::gather</code> is called, it roughly performs the following steps:</p>

<ul>
  <li>Create a <a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.Downstream.html"><code class="language-plaintext highlighter-rouge">Downstream</code></a> object which, when given an element of the gatherer’s output type, passes it to the next stage in the pipeline.</li>
  <li>Obtain the gatherer’s private state object by invoking the <code class="language-plaintext highlighter-rouge">get()</code> method of its initializer.</li>
  <li>Obtain the gatherer’s integrator by invoking its <a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.html#integrator()"><code class="language-plaintext highlighter-rouge">integrator()</code></a> method.</li>
  <li>While there are more input elements, invoke the integrator’s <a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherer.Integrator.html#integrate(A,T,java.util.stream.Gatherer.Downstream)"><code class="language-plaintext highlighter-rouge">integrate(...)</code></a> method, passing it the state object, the next element, and the downstream object. Terminate if that method returns false.</li>
  <li>Obtain the gatherer’s finisher and invoke it with the state and downstream objects.</li>
</ul>

<p>These steps are generic enough to allow every currently existing intermediate stream operation to be expressed in a custom gatherer. For example, the <code class="language-plaintext highlighter-rouge">Stream::map</code> operation turns each <code class="language-plaintext highlighter-rouge">T</code> element into a <code class="language-plaintext highlighter-rouge">U</code> element, so it is simply a stateless one-to-one gatherer. Likewise, the <code class="language-plaintext highlighter-rouge">Stream::filter</code> operation is a stateless one-to-many gatherer. This makes every stream pipeline conceptually equivalent to:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">stream</span>
    <span class="o">.</span><span class="na">gather</span><span class="o">(...)</span>
    <span class="o">.</span><span class="na">gather</span><span class="o">(...)</span>
    <span class="o">.</span><span class="na">gather</span><span class="o">(...)</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(...);</span>
</code></pre></div></div>

<h4 id="built-in-gatherers">Built-in gatherers</h4>

<p>As part of this JEP a few built-in gatherers are introduced:</p>

<dl>
  <dt><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#fold(java.util.function.Supplier,java.util.function.BiFunction)"><code class="language-plaintext highlighter-rouge">fold</code></a></dt>
  <dd>A stateful many-to-one gatherer which constructs an aggregate incrementally and emits that aggregate when no more input elements exist.</dd>
  <dt><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#mapConcurrent(int,java.util.function.Function)"><code class="language-plaintext highlighter-rouge">mapConcurrent</code></a></dt>
  <dd>A stateful one-to-one gatherer which invokes a supplied function for each input element concurrently, up to a supplied limit.</dd>
  <dt><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#scan(java.util.function.Supplier,java.util.function.BiFunction)"><code class="language-plaintext highlighter-rouge">scan</code></a></dt>
  <dd>A stateful one-to-one gatherer which applies a supplied function to the current state and the current element to produce the next element, which it passes downstream.</dd>
  <dt><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#windowFixed(int)"><code class="language-plaintext highlighter-rouge">windowFixed</code></a></dt>
  <dd>A stateful many-to-many gatherer which groups input elements into lists of a supplied size, emitting the windows downstream when they are full.</dd>
  <dt><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#windowSliding(int)"><code class="language-plaintext highlighter-rouge">windowSliding</code></a></dt>
  <dd>A stateful many-to-many gatherer which groups input elements into lists of a supplied size. After the first window, each subsequent window is created from a copy of its predecessor by dropping the first element and appending the next element from the input stream.</dd>
</dl>

<h4 id="example-of-a-custom-gatherer">Example of a Custom Gatherer</h4>

<p>Let’s look at a custom gatherer that implements the <code class="language-plaintext highlighter-rouge">distinctBy</code> operation we referred to earlier.</p>

<blockquote>
  <p>This example is based on Karl Heinz Marbaise’s <a href="https://blog.soebes.io/posts/2024/01/2024-01-07-jdk-gatherer/">excellent blog post on stream gatherers</a> - do check it out if you wish to know more!</p>
</blockquote>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="o">&lt;</span><span class="no">T</span><span class="o">,</span> <span class="no">A</span><span class="o">&gt;</span> <span class="nc">Gatherer</span><span class="o">&lt;</span><span class="no">T</span><span class="o">,</span> <span class="o">?,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="nf">distinctBy</span><span class="o">(</span><span class="nc">Function</span><span class="o">&lt;?</span> <span class="kd">super</span> <span class="no">T</span><span class="o">,</span> <span class="o">?</span> <span class="kd">extends</span> <span class="no">A</span><span class="o">&gt;</span> <span class="n">classifier</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">&lt;</span><span class="no">A</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="no">T</span><span class="o">&gt;&gt;&gt;</span> <span class="n">initializer</span> <span class="o">=</span> <span class="nl">HashMap:</span><span class="o">:</span><span class="k">new</span><span class="o">;</span>
    <span class="nc">Gatherer</span><span class="o">.</span><span class="na">Integrator</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">&lt;</span><span class="no">A</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="no">T</span><span class="o">&gt;&gt;,</span> <span class="no">T</span><span class="o">,</span> <span class="no">T</span><span class="o">&gt;</span> <span class="n">integrator</span> <span class="o">=</span> <span class="o">(</span><span class="n">state</span><span class="o">,</span> <span class="n">element</span><span class="o">,</span> <span class="n">_</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="o">{</span>
        <span class="n">state</span><span class="o">.</span><span class="na">computeIfAbsent</span><span class="o">(</span><span class="n">classifier</span><span class="o">.</span><span class="na">apply</span><span class="o">(</span><span class="n">element</span><span class="o">),</span> <span class="n">_</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o">&lt;&gt;()).</span><span class="na">add</span><span class="o">(</span><span class="n">element</span><span class="o">);</span>
        <span class="k">return</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">// true, because more elements need to be consumed</span>
    <span class="o">};</span>
    <span class="nc">BiConsumer</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">&lt;</span><span class="no">A</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="no">T</span><span class="o">&gt;&gt;,</span> <span class="nc">Gatherer</span><span class="o">.</span><span class="na">Downstream</span><span class="o">&lt;?</span> <span class="kd">super</span> <span class="no">T</span><span class="o">&gt;&gt;</span> <span class="n">finisher</span> <span class="o">=</span> <span class="o">(</span><span class="n">state</span><span class="o">,</span> <span class="n">downstream</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="o">{</span>
        <span class="n">state</span><span class="o">.</span><span class="na">forEach</span><span class="o">((</span><span class="n">_</span><span class="o">,</span> <span class="n">value</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">downstream</span><span class="o">.</span><span class="na">push</span><span class="o">(</span><span class="n">value</span><span class="o">.</span><span class="na">getLast</span><span class="o">()));</span>
    <span class="o">};</span>
    <span class="k">return</span> <span class="nc">Gatherer</span><span class="o">.</span><span class="na">ofSequential</span><span class="o">(</span><span class="n">initializer</span><span class="o">,</span> <span class="n">integrator</span><span class="o">,</span> <span class="n">finisher</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<p>…and this is how you could use it:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">guitars</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
        <span class="o">.</span><span class="na">gather</span><span class="o">(</span><span class="n">distinctBy</span><span class="o">(</span><span class="nl">Guitar:</span><span class="o">:</span><span class="n">guitarStyle</span><span class="o">))</span>
        <span class="o">.</span><span class="na">forEach</span><span class="o">(</span><span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">::</span><span class="n">println</span><span class="o">);</span>
</code></pre></div></div>

<p>…which would yield the following output:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Guitar[name=Taylor GS Mini-e Koa, guitarStyle=WESTERN]
Guitar[name=Fender Stratocaster, guitarStyle=ELECTRIC]
Guitar[name=Cordoba F7 Paco Flamenco, guitarStyle=CLASSICAL]
</code></pre></div></div>

<h4 id="no-new-intermediate-operations">No New Intermediate Operations</h4>

<p>In conclusion the JEP also states that no new intermediate operations will be added to the <code class="language-plaintext highlighter-rouge">Stream</code> class to represent the newly-added built-in gatherers. This is because the language designers want the Stream API to remain concise and easy to learn. The JEP does suggest that adding new intermediate operations in a later round of preview could be an option, once they have proven that they are broadly useful.</p>

<h4 id="whats-different-from-java-21-11">What’s Different From Java 21?</h4>

<p>Up until Java 21, intermediate stream operations were limited to the ones that were built-in. In contrast, Java 22 includes support for custom intermediate operations.</p>

<p>Note that this JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to take the feature for a spin.</p>

<h4 id="more-information-11">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/461">JEP 461</a> and the <a href="https://dev.to/khmarbaise/jdk22-gatherer-2a6e">blog post on gatherers</a> by Karl Heinz Marbaise.</p>

<h2 id="final-thoughts">Final thoughts</h2>

<p>It seems clear to me that Java 22 is ready to rock, with no less than 12 JEPs delivered! And that’s not even all that’s new: <a href="https://jdk.java.net/22/release-notes">many other updates</a> were included in this release, including various performance and stability updates. Our favourite language is clearly more alive than ever, and on top of that it’ll probably attract more newcomers due to the features that focus on starting projects. Here’s to many happy hours of development with Java 22!</p>]]></content><author><name>Hanno Embregts</name></author><category term="java" /><summary type="html"><![CDATA[Java 22 is here, and it's ready to rock! Boasting a set of 12 JEPs, it finalizes features like 'unnamed variables and patterns' and previews new ones like 'statements before super(...)' and 'stream gatherers'. This post has all the info!]]></summary></entry><entry><title type="html">Java 21 is Available Today, And It’s Quite the Update</title><link href="https://hanno.codes/2023/09/19/java-21-release-day/" rel="alternate" type="text/html" title="Java 21 is Available Today, And It’s Quite the Update" /><published>2023-09-19T02:30:00+00:00</published><updated>2023-09-19T02:30:00+00:00</updated><id>https://hanno.codes/2023/09/19/java-21-release-day</id><content type="html" xml:base="https://hanno.codes/2023/09/19/java-21-release-day/"><![CDATA[<p>Today’s the first day of Java 21’s availability! It’s been six months since Java 20 was released, so it’s time for another fresh wave of Java features. This post takes you on a tour of the JEPs that are associated with this release and it gives you a brief introduction to each of them. Where applicable the differences with Java 20 are highlighted and a few typical use cases are provided, so that you’ll be more than ready to use these features after reading this!</p>

<p><img src="/assets/images/blog/ready-set-go.jpg" alt="Ready, set, go!" /></p>
<blockquote>
  <p>Image from <a href="https://pxhere.com/en/photo/47097">PxHere</a></p>
</blockquote>

<h2 id="from-project-amber">From Project Amber</h2>

<p>Java 21 contains five features that originated from <a href="https://openjdk.org/projects/amber/">Project Amber</a>:</p>

<ul>
  <li>Pattern Matching for switch;</li>
  <li>Record Patterns;</li>
  <li>Unnamed Patterns and Variables;</li>
  <li>Unnamed Classes and Instance Main Methods;</li>
  <li>String Templates.</li>
</ul>

<blockquote>
  <p>The goal of Project Amber is to explore and incubate smaller, productivity-oriented Java language features.</p>
</blockquote>

<h3 id="jep-441-pattern-matching-for-switch">JEP 441: Pattern Matching for switch</h3>

<p>The feature ‘Pattern Matching for switch’ (first introduced in Java 17) has reached completion status, now that Java 21 has been released.</p>

<p>Since Java 16 we’ve been able to avoid casting after <code class="language-plaintext highlighter-rouge">instanceof</code> checks by using ‘Pattern Matching for instanceof’. Let’s refresh our memory with a code example.</p>

<blockquote>
  <p>All code examples about Project Amber features were taken from my conference talk <a href="https://hanno.codes/talks/#pattern-matching-small-enhancement-or-major-feature">“Pattern Matching: Small Enhancement or Major Feature?”</a>.</p>
</blockquote>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="nc">String</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">String</span> <span class="n">formatted</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">effect</span> <span class="k">instanceof</span> <span class="nc">Delay</span> <span class="n">de</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">formatted</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Delay active of %d ms."</span><span class="o">,</span> <span class="n">de</span><span class="o">.</span><span class="na">timeInMs</span><span class="o">());</span>
    <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">effect</span> <span class="k">instanceof</span> <span class="nc">Reverb</span> <span class="n">re</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">formatted</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Reverb active of type %s and roomSize %d."</span><span class="o">,</span> <span class="n">re</span><span class="o">.</span><span class="na">name</span><span class="o">(),</span> <span class="n">re</span><span class="o">.</span><span class="na">roomSize</span><span class="o">());</span>
    <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">effect</span> <span class="k">instanceof</span> <span class="nc">Overdrive</span> <span class="n">ov</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">formatted</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Overdrive active with gain %d."</span><span class="o">,</span> <span class="n">ov</span><span class="o">.</span><span class="na">gain</span><span class="o">());</span>
    <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">effect</span> <span class="k">instanceof</span> <span class="nc">Tremolo</span> <span class="n">tr</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">formatted</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tremolo active with depth %d and rate %d."</span><span class="o">,</span> <span class="n">tr</span><span class="o">.</span><span class="na">depth</span><span class="o">(),</span> <span class="n">tr</span><span class="o">.</span><span class="na">rate</span><span class="o">());</span>
    <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">effect</span> <span class="k">instanceof</span> <span class="nc">Tuner</span> <span class="n">tu</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">formatted</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tuner active with pitch %d. Muting all signal!"</span><span class="o">,</span> <span class="n">tu</span><span class="o">.</span><span class="na">pitchInHz</span><span class="o">());</span>
    <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
        <span class="n">formatted</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Unknown effect active: %s."</span><span class="o">,</span> <span class="n">effect</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="n">formatted</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This code is still riddled with ceremony, though. On top of that it leaves room for subtle bugs — what if you added an else-if branch that didn’t assign anything to <code class="language-plaintext highlighter-rouge">formatted</code>? Let’s see what pattern matching in a switch statement (or even better: in a switch <em>expression</em>) would look like:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="nc">String</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="nf">switch</span><span class="o">(</span><span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">case</span> <span class="nc">Delay</span> <span class="n">de</span>      <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Delay active of %d ms."</span><span class="o">,</span> <span class="n">de</span><span class="o">.</span><span class="na">timeInMs</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Reverb</span> <span class="n">re</span>     <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Reverb active of type %s and roomSize %d."</span><span class="o">,</span> <span class="n">re</span><span class="o">.</span><span class="na">name</span><span class="o">(),</span> <span class="n">re</span><span class="o">.</span><span class="na">roomSize</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Overdrive</span> <span class="n">ov</span>  <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Overdrive active with gain %d."</span><span class="o">,</span> <span class="n">ov</span><span class="o">.</span><span class="na">gain</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Tremolo</span> <span class="n">tr</span>    <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tremolo active with depth %d and rate %d."</span><span class="o">,</span> <span class="n">tr</span><span class="o">.</span><span class="na">depth</span><span class="o">(),</span> <span class="n">tr</span><span class="o">.</span><span class="na">rate</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Tuner</span> <span class="n">tu</span>      <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tuner active with pitch %d. Muting all signal!"</span><span class="o">,</span> <span class="n">tu</span><span class="o">.</span><span class="na">pitchInHz</span><span class="o">());</span>
        <span class="k">case</span> <span class="kc">null</span><span class="o">,</span> <span class="k">default</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Unknown or empty effect active: %s."</span><span class="o">,</span> <span class="n">effect</span><span class="o">);</span>
    <span class="o">};</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Pattern matching for switch made our code far more elegant here. We’re even able to address possible <code class="language-plaintext highlighter-rouge">null</code>s by defining a specific case for them or combining it with the default case (which is what we’ve done here).</p>

<p>Checking an additional condition after the pattern match is easily done with a <em>guard</em> (the part after the <code class="language-plaintext highlighter-rouge">when</code> keyword in the code below):</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="nc">String</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">,</span> <span class="nc">Guitar</span> <span class="n">guitar</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="nf">switch</span><span class="o">(</span><span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">case</span> <span class="nc">Delay</span> <span class="n">de</span>      <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Delay active of %d ms."</span><span class="o">,</span> <span class="n">de</span><span class="o">.</span><span class="na">timeInMs</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Reverb</span> <span class="n">re</span>     <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Reverb active of type %s and roomSize %d."</span><span class="o">,</span> <span class="n">re</span><span class="o">.</span><span class="na">name</span><span class="o">(),</span> <span class="n">re</span><span class="o">.</span><span class="na">roomSize</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Overdrive</span> <span class="n">ov</span>  <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Overdrive active with gain %d."</span><span class="o">,</span> <span class="n">ov</span><span class="o">.</span><span class="na">gain</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Tremolo</span> <span class="n">tr</span>    <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tremolo active with depth %d and rate %d."</span><span class="o">,</span> <span class="n">tr</span><span class="o">.</span><span class="na">depth</span><span class="o">(),</span> <span class="n">tr</span><span class="o">.</span><span class="na">rate</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Tuner</span> <span class="n">tu</span> <span class="n">when</span> <span class="o">!</span><span class="n">guitar</span><span class="o">.</span><span class="na">isInTune</span><span class="o">()</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tuner active with pitch %d. Muting all signal!"</span><span class="o">,</span> <span class="n">tu</span><span class="o">.</span><span class="na">pitchInHz</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Tuner</span> <span class="n">tu</span>      <span class="o">-&gt;</span> <span class="s">"Guitar is already in tune."</span><span class="o">;</span>
        <span class="k">case</span> <span class="kc">null</span><span class="o">,</span> <span class="k">default</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Unknown or empty effect active: %s."</span><span class="o">,</span> <span class="n">effect</span><span class="o">);</span>
    <span class="o">};</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here, the guard makes sure that intricate boolean logic can still be expressed in a concise way. Having to nest <code class="language-plaintext highlighter-rouge">if</code> statements to test this logic within a case branch would not only be more verbose, but also potentially introduce subtle bugs that we set out to avoid in the first place.</p>

<h4 id="whats-different-from-java-20">What’s Different From Java 20?</h4>

<p>There have been two major changes from <a href="https://openjdk.org/jeps/433">the previous JEP</a>:</p>

<ul>
  <li>An earlier version of the ‘Pattern Matching for switch’ feature came with <a href="https://docs.oracle.com/en/java/javase/17/language/pattern-matching.html#GUID-A59EF0C7-4CB7-4555-986D-0FD804555C25">parenthesized patterns</a>, which helped resolve parsing ambiguities back when guards were still expressed with the <code class="language-plaintext highlighter-rouge">&amp;&amp;</code> operator. Now that the <code class="language-plaintext highlighter-rouge">when</code> keyword has replaced the <code class="language-plaintext highlighter-rouge">&amp;&amp;</code> operator for guards, the value for parenthesized patterns has decreased significantly. So the choice was made to remove them in Java 21.</li>
  <li>Switch expressions and statements now allow qualified enum constants as case constants. This makes it easier to do an exhaustive <code class="language-plaintext highlighter-rouge">switch</code> on an interface type when both a class and an enum implementation of that interface exists. The JEP description has <a href="https://openjdk.org/jeps/441#Switches-and-enum-constants">a good example of this mechanism</a>, should you wish to learn more about it.</li>
</ul>

<h4 id="more-information">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/441">JEP 441</a>. Or if you want to try out pattern matching for switch with the provided code examples, then here’s a <a href="https://github.com/hannotify/pattern-matching-music-store">GitHub repository</a> to get you started.</p>

<h3 id="jep-440-record-patterns">JEP 440: Record Patterns</h3>

<p>With the introduction of <em>record patterns</em>, deconstructing records is now possible, along with nesting record and type patterns to enable a powerful, declarative, and composable form of data navigation and processing.</p>

<p><a href="https://openjdk.org/jeps/395">Records</a> are transparent carriers for data. Code that receives an instance of a record will typically extract the data, known as the components. This was also the case in our ‘Pattern Matching for switch’ code example, if we assume that all implementations of the <code class="language-plaintext highlighter-rouge">Effect</code> interface were in fact records there. In that piece of code it is clear that the pattern variables only serve to access the record fields. Using record patterns we can avoid having to create pattern variables altogether:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="nc">String</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="nf">switch</span><span class="o">(</span><span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">case</span> <span class="nf">Delay</span><span class="o">(</span><span class="kt">int</span> <span class="n">timeInMs</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Delay active of %d ms."</span><span class="o">,</span> <span class="n">timeInMs</span><span class="o">);</span>
        <span class="k">case</span> <span class="nf">Reverb</span><span class="o">(</span><span class="nc">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">int</span> <span class="n">roomSize</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Reverb active of type %s and roomSize %d."</span><span class="o">,</span> <span class="n">name</span><span class="o">,</span> <span class="n">roomSize</span><span class="o">);</span>
        <span class="k">case</span> <span class="nf">Overdrive</span><span class="o">(</span><span class="kt">int</span> <span class="n">gain</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Overdrive active with gain %d."</span><span class="o">,</span> <span class="n">gain</span><span class="o">);</span>
        <span class="k">case</span> <span class="nf">Tremolo</span><span class="o">(</span><span class="kt">int</span> <span class="n">depth</span><span class="o">,</span> <span class="kt">int</span> <span class="n">rate</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tremolo active with depth %d and rate %d."</span><span class="o">,</span> <span class="n">depth</span><span class="o">,</span> <span class="n">rate</span><span class="o">);</span>
        <span class="k">case</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">int</span> <span class="n">pitchInHz</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tuner active with pitch %d. Muting all signal!"</span><span class="o">,</span> <span class="n">pitchInHz</span><span class="o">);</span>
        <span class="k">case</span> <span class="kc">null</span><span class="o">,</span> <span class="k">default</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Unknown or empty effect active: %s."</span><span class="o">,</span> <span class="n">effect</span><span class="o">);</span>
    <span class="o">};</span>
<span class="o">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Delay(int timeInMs)</code> is a record pattern here, deconstructing the <code class="language-plaintext highlighter-rouge">Delay</code> instance into its components. And this mechanism can become even more powerful when we apply it to a more complicated object graph by using <em>nested</em> record patterns:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">record</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">int</span> <span class="n">pitchInHz</span><span class="o">,</span> <span class="nc">Note</span> <span class="n">note</span><span class="o">)</span> <span class="kd">implements</span> <span class="nc">Effect</span> <span class="o">{}</span>
<span class="n">record</span> <span class="nf">Note</span><span class="o">(</span><span class="nc">String</span> <span class="n">note</span><span class="o">)</span> <span class="o">{}</span>

<span class="kd">class</span> <span class="nc">TunerApplier</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="nc">String</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">,</span> <span class="nc">Guitar</span> <span class="n">guitar</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="nf">switch</span><span class="o">(</span><span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">case</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">int</span> <span class="n">pitch</span><span class="o">,</span> <span class="nc">Note</span><span class="o">(</span><span class="nc">String</span> <span class="n">note</span><span class="o">))</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tuner active with pitch %d on note %s"</span><span class="o">,</span> <span class="n">pitch</span><span class="o">,</span> <span class="n">note</span><span class="o">);</span>
        <span class="o">};</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<h4 id="inference-of-type-arguments">Inference of type arguments</h4>

<p>Nested record patterns also benefit from <em>inference of type arguments</em>. For example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">TunerApplier</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="nc">String</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">,</span> <span class="nc">Guitar</span> <span class="n">guitar</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="nf">switch</span><span class="o">(</span><span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">case</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">var</span> <span class="n">pitch</span><span class="o">,</span> <span class="nc">Note</span><span class="o">(</span><span class="kt">var</span> <span class="n">note</span><span class="o">))</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tuner active with pitch %d on note %s"</span><span class="o">,</span> <span class="n">pitch</span><span class="o">,</span> <span class="n">note</span><span class="o">);</span>
        <span class="o">};</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here the type arguments for the nested pattern <code class="language-plaintext highlighter-rouge">Tuner(var pitch, Note(var note))</code> are inferred. This only works with nested patterns for now; type patterns do not yet support implicit inference of type arguments. So the type pattern <code class="language-plaintext highlighter-rouge">Tuner tu</code> is always treated as a raw type pattern.</p>

<h4 id="whats-different-from-java-20-1">What’s Different From Java 20?</h4>

<p>Apart from some minor editorial changes and the fact that the feature is now in its final state, the main change since the second preview is the removal of support for record patterns appearing in the header of an enhanced for statement. Java 20 <a href="https://hanno.codes/2023/03/21/java-20-release-day-heres-whats-new/#enhanced-for-statements">introduced this feature</a>, but it was dropped in Java 21 because it “may need a significant redesign, to better align with other features under consideration” (see <a href="https://bugs.openjdk.org/browse/JDK-8304401">this OpenJDK ticket</a> for more information). This may seem strange, but this is the way it can be with preview features: they are fully specified and implemented, and yet impermanent until the feature has been fully delivered. Not to worry though, JEP 440 also hints that support for record patterns in enhanced for statements may be re-proposed in a future JEP, presumably when it’s able to be better aligned with other features under consideration.</p>

<h4 id="more-information-1">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/440">JEP 440</a>. Or if you want to try out record patterns with the provided code examples,, then here’s a <a href="https://github.com/hannotify/pattern-matching-music-store">GitHub repository</a> to get you started.</p>

<h3 id="jep-443-unnamed-patterns-and-variables-preview">JEP 443: Unnamed Patterns and Variables (Preview)</h3>

<p>Data processing in Java has become increasingly streamlined since the introduction of <a href="https://openjdk.org/jeps/395">records</a> and <a href="#jep-440-record-patterns">record patterns</a>. But in some cases writing out an entire record pattern when some record components aren’t even used in the logic that follows can be both cumbersome and confusing. Let’s consider the following code example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="kt">boolean</span> <span class="nf">isDelayTimeEqualToReverbRoomSize</span><span class="o">(</span><span class="nc">EffectLoop</span> <span class="n">effectLoop</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">effectLoop</span> <span class="k">instanceof</span> <span class="nf">EffectLoop</span><span class="o">(</span><span class="nc">Delay</span><span class="o">(</span><span class="kt">int</span> <span class="n">timeInMs</span><span class="o">),</span> <span class="nc">Reverb</span><span class="o">(</span><span class="nc">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">int</span> <span class="n">roomSize</span><span class="o">)))</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">timeInMs</span> <span class="o">==</span> <span class="n">roomSize</span><span class="o">;</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here, the logic doesn’t reference the reverb name whatsoever, but Java currently doesn’t have a way to indicate this omission might be intentional. And so the entire record pattern has been written out, leading future readers of this code to doubt the correctness of the implementation.</p>

<h4 id="unnamed-patterns">Unnamed Patterns</h4>

<p>JEP 443 proposes <em>unnamed patterns</em>, which could improve the situation here:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="kt">boolean</span> <span class="nf">isDelayTimeEqualToReverbRoomSize</span><span class="o">(</span><span class="nc">EffectLoop</span> <span class="n">effectLoop</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">effectLoop</span> <span class="k">instanceof</span> <span class="nf">EffectLoop</span><span class="o">(</span><span class="nc">Delay</span><span class="o">(</span><span class="kt">int</span> <span class="n">timeInMs</span><span class="o">),</span> <span class="nc">Reverb</span><span class="o">(</span><span class="n">_</span><span class="o">,</span> <span class="kt">int</span> <span class="n">roomSize</span><span class="o">)))</span> <span class="o">{</span>
        <span class="k">return</span> <span class="n">timeInMs</span> <span class="o">==</span> <span class="n">roomSize</span><span class="o">;</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The underscore denotes the unnamed pattern here: it is an unconditional pattern which binds nothing. You can use it to indicate that it doesn’t matter to what first value the pattern matches the <code class="language-plaintext highlighter-rouge">Reverb</code>, as long as the second parameter can be matched to an <code class="language-plaintext highlighter-rouge">int</code>.</p>

<h4 id="unnamed-pattern-variables">Unnamed Pattern Variables</h4>

<p><em>Unnamed pattern variables</em> are also proposed by this JEP. You can use them whenever you care about the type your record pattern will match, but when you don’t need any value bound to the pattern variable. Imagine we want our tuner code to also support tuning piano keys in the future, then we could use unnamed pattern variables like this:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="kt">void</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">,</span> <span class="nc">Piano</span> <span class="n">piano</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="k">switch</span><span class="o">(</span><span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">case</span> <span class="nf">Tuner</span><span class="o">(</span><span class="nc">FlatNote</span> <span class="n">_</span><span class="o">),</span> <span class="nc">Tuner</span><span class="o">(</span><span class="nc">SharpNote</span> <span class="n">_</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="s">"Tuning one of the black keys..."</span><span class="o">;</span>
        <span class="k">case</span> <span class="nf">Tuner</span><span class="o">(</span><span class="nc">RegularNote</span> <span class="n">_</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="s">"Tuning one of the white keys..."</span><span class="o">;</span>
        <span class="k">default</span> <span class="o">-&gt;</span> <span class="s">"An unknown effect is active..."</span><span class="o">;</span>
    <span class="o">});</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here, we execute specific logic when we encounter a tuner that tunes a flat (♭) or sharp (♯) note. We use an unnamed pattern variable, because the logic acts on the matched type only - the value can be safely ignored.</p>

<h4 id="unnamed-variables">Unnamed Variables</h4>

<p><em>Unnamed variables</em> are useful in situations where variables are unused and their names are irrelevant, for example when keeping a counter variable within the body of a for-each loop:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">guitarCount</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
<span class="k">for</span> <span class="o">(</span><span class="nc">Guitar</span> <span class="n">guitar</span> <span class="o">:</span> <span class="n">guitars</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">guitarCount</span> <span class="o">&lt;</span> <span class="no">LIMIT</span><span class="o">)</span> <span class="o">{</span> 
        <span class="n">guitarCount</span><span class="o">++;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">guitar</code> variable is declared and populated here, but it is never used. Unfortunately, its intentional non-use doesn’t come across as such to the reader. Moreover, static code analysis tools like Sonar will probably complain about the unused variable, raising suspicions even more. Introducing an unnamed variable can better convey the intent of the code:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">guitarCount</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
<span class="k">for</span> <span class="o">(</span><span class="nc">Guitar</span> <span class="n">_</span> <span class="o">:</span> <span class="n">guitars</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">guitarCount</span> <span class="o">&lt;</span> <span class="no">LIMIT</span><span class="o">)</span> <span class="o">{</span> 
        <span class="n">guitarCount</span><span class="o">++;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Another good example could be handling exceptions in a generic way:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">lesPaul</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Guitar</span><span class="o">(</span><span class="s">"Les Paul"</span><span class="o">);</span>
<span class="k">try</span> <span class="o">{</span> 
    <span class="n">cart</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">stock</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">lesPaul</span><span class="o">,</span> <span class="n">guitarCount</span><span class="o">));</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">OutOfStockException</span> <span class="n">_</span><span class="o">)</span> <span class="o">{</span> 
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Sorry, out of stock!"</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Keep in mind that unnamed variables only make sense when they’re not visible outside a method, so they currently only work with local variables, exception parameters and lambda parameters. The theoretical concept of <em>unnamed method parameters</em> is briefly touched upon in the JEP, but supporting that comes with enough challenges to at least warrant postponing it to a future JEP.</p>

<h4 id="whats-different-from-java-20-2">What’s Different From Java 20?</h4>

<p>Java 20 didn’t contain anything related to unnamed patterns and variables yet, so Java 21 is the first time we get to experiment with them. Note that the JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to be able to take the feature for a spin.</p>

<h4 id="more-information-2">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/443">JEP 443</a>.</p>

<h3 id="jep-445-unnamed-classes-and-instance-main-methods-preview">JEP 445: Unnamed Classes and Instance Main Methods (Preview)</h3>

<p>Java’s take on the classic <a href="https://en.wikipedia.org/wiki/%22Hello,_World!%22_program">Hello, World!</a> program is notoriously verbose:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="o">{</span> 
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span> 
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello, World!"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>On top of that, it forces newcomers to Java to grasp a few concepts that they certainly don’t need on their first day of Java programming:</p>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">public</code> access modifier and the role it plays in encapsulating units of code, together with its counterparts <code class="language-plaintext highlighter-rouge">private</code>, <code class="language-plaintext highlighter-rouge">protected</code> and default;</li>
  <li>The <code class="language-plaintext highlighter-rouge">String[] args</code> parameter, that allows the operating system’s shell to pass arguments to the program;</li>
  <li>The <code class="language-plaintext highlighter-rouge">static</code> modifier and how it’s part of Java’s class-and-object model.</li>
</ul>

<p>The motivation for this JEP is to help programmers that are new to Java by introducing concepts in the right order, starting with the more fundamental ones. This is done by hiding the unnecessary details until they are useful in larger programs.</p>

<h4 id="changing-the-launch-protocol">Changing the Launch Protocol</h4>

<p>To achieve this, the JEP proposes the following changes to the launch protocol:</p>

<ul>
  <li>allow <em>instance main methods</em>, which are not <code class="language-plaintext highlighter-rouge">static</code> and don’t need a <code class="language-plaintext highlighter-rouge">public</code> modifier, nor a <code class="language-plaintext highlighter-rouge">String[]</code> parameter;</li>
</ul>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="o">{</span> 
    <span class="kt">void</span> <span class="nf">main</span><span class="o">()</span> <span class="o">{</span> <span class="c1">// this is an instance main method</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello, World!"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<ul>
  <li>introduce <em>unnamed classes</em> to make the <code class="language-plaintext highlighter-rouge">class</code> declaration implicit;</li>
</ul>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">main</span><span class="o">()</span> <span class="o">{</span> <span class="c1">// this is an instance main method inside of an unnamed class</span>
    <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello, World!"</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<h4 id="selecting-a-main-method">Selecting a Main Method</h4>

<p>In Java 21, when launching a class, the launch protocol chooses the first of the following methods to invoke:</p>

<ul>
  <li>A <code class="language-plaintext highlighter-rouge">static void main(String[] args)</code> method of non-private access (i.e., <code class="language-plaintext highlighter-rouge">public</code>, <code class="language-plaintext highlighter-rouge">protected</code> or package) declared in the launched class,</li>
  <li>A <code class="language-plaintext highlighter-rouge">static void main()</code> method of non-private access declared in the launched class,</li>
  <li>A <code class="language-plaintext highlighter-rouge">void main(String[] args)</code> instance method of non-private access declared in the launched class or inherited from a superclass, or, finally,</li>
  <li>A <code class="language-plaintext highlighter-rouge">void main()</code> instance method of non-private access declared in the launched class or inherited from a superclass.</li>
</ul>

<h4 id="unnamed-classes">Unnamed Classes</h4>

<p>With the introduction of unnamed classes, the Java compiler will implicitly consider a method that is not enclosed in a class declaration, as well as any unenclosed fields and any classes declared in the file, to be members of an unnamed top-level class. 
An unnamed class always belongs to the unnamed package, is <code class="language-plaintext highlighter-rouge">final</code>, and can’t implement interfaces or extend classes except <code class="language-plaintext highlighter-rouge">Object</code>. You can’t reference it by name or use method references for its static methods, but you can use <code class="language-plaintext highlighter-rouge">this</code> and make method references to its instance methods. Unnamed classes can’t be instantiated or referenced by name in code. They’re mainly used as program entry points and must have a <code class="language-plaintext highlighter-rouge">main</code> method, enforced by the Java compiler.</p>

<h4 id="whats-different-from-java-20-3">What’s Different From Java 20?</h4>

<p>Java 20 didn’t contain anything related to unnamed classes and instance main methods yet, so Java 21 is the first time we get to experiment with them. Note that the JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to be able to take the feature for a spin.</p>

<h4 id="more-information-3">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/445">JEP 445</a>.</p>

<h3 id="jep-430-string-templates-preview">JEP 430: String Templates (Preview)</h3>

<p>There are currently multiple ways in Java to compose a string from literal text and expressions:</p>

<ul>
  <li>String concatenation with the <code class="language-plaintext highlighter-rouge">+</code> operator;</li>
  <li><code class="language-plaintext highlighter-rouge">StringBuilder</code>;</li>
  <li><code class="language-plaintext highlighter-rouge">String::format</code> or <code class="language-plaintext highlighter-rouge">String::formatted</code>;</li>
  <li><code class="language-plaintext highlighter-rouge">java.text.MessageFormat</code></li>
</ul>

<p>However, these mechanisms come with drawbacks. They involve hard-to-read code (<code class="language-plaintext highlighter-rouge">+</code> operator) or verbose code (<code class="language-plaintext highlighter-rouge">StringBuilder</code>), they separate the input string from the parameters (<code class="language-plaintext highlighter-rouge">String::format</code>) or they require a lot of ceremony (<code class="language-plaintext highlighter-rouge">MessageFormat</code>).</p>

<p><em>String interpolation</em> is a mechanism that many programming languages offer as a solution to these drawbacks. But string interpolation comes with a drawback of its own: interpolated strings need to be manually validated by the developer to avoid dangerous risks like <a href="https://en.wikipedia.org/wiki/SQL_injection">SQL injection</a>.</p>

<p>This JEP proposes the ‘String Templates’ feature: a template-based mechanism for composing strings that offers the benefits of interpolation, but would be less prone to introducing security vulnerabilities. A <em>template expression</em> is a new kind of expression in Java, that can perform string interpolation but is also programmable in a way that helps developers compose strings safely and efficiently.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">guitarType</span> <span class="o">=</span> <span class="s">"Les Paul"</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">STR</span><span class="o">.</span><span class="s">"I bought a \{guitarType} yesterday."</span><span class="o">);</span>
<span class="c1">// outputs "I bought a Les Paul yesterday."</span>
</code></pre></div></div>

<p>The template expression <code class="language-plaintext highlighter-rouge">STR."I bought a \{guitarType} yesterday."</code> consists of:</p>

<ul>
  <li>A template processor (<code class="language-plaintext highlighter-rouge">STR</code>);</li>
  <li>A dot character, as seen in other kinds of expressions; and</li>
  <li>A template (<code class="language-plaintext highlighter-rouge">"I bought a \{guitarType} yesterday."</code>) which contains an embedded expression (<code class="language-plaintext highlighter-rouge">\{guitarType}</code>).</li>
</ul>

<p>When a template expression is evaluated at run time, its template processor combines the literal text in the template with the values of the embedded expressions in order to produce a result. The embedded expressions can perform arithmetic, invoke methods and access fields:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">price</span> <span class="o">=</span> <span class="mi">12</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">STR</span><span class="o">.</span><span class="s">"A set of strings costs \{price} dollars; so each string costs \{price / 6} dollars."</span><span class="o">);</span>
<span class="c1">// outputs "A set of strings costs 12 dollars; so each string costs 2 dollars."</span>
</code></pre></div></div>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">record</span> <span class="nf">Guitar</span><span class="o">(</span><span class="nc">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">inTune</span><span class="o">)</span> <span class="o">{}</span>
<span class="kd">class</span> <span class="nc">GuitarTuner</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">...</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="kt">var</span> <span class="n">guitar</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Guitar</span><span class="o">(</span><span class="s">"Gibson Les Paul Standard '50s Heritage Cherry Sunburst"</span><span class="o">,</span> <span class="kc">false</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">STR</span><span class="o">.</span><span class="s">"This guitar is \{guitar.inTune() ? "" : "</span><span class="n">not</span><span class="s">"} in tune."</span><span class="o">);</span>
        <span class="c1">// outputs "This guitar is not in tune.</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>As you can see, double-quote characters can be used inside embedded expressions without escaping them as <code class="language-plaintext highlighter-rouge">\"</code>, making the switch from concatenation (using <code class="language-plaintext highlighter-rouge">+</code>) to template expressions easier. Multi-line template expressions are also possible; they use a syntax similar to that of <a href="https://docs.oracle.com/javase/specs/jls/se20/html/jls-3.html#jls-3.10.6">text blocks</a>:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">title</span> <span class="o">=</span> <span class="s">"My Online Guitar Store"</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">text</span> <span class="o">=</span> <span class="s">"Buy your next Les Paul here!"</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">html</span> <span class="o">=</span> <span class="no">STR</span><span class="o">.</span><span class="s">"""
        &lt;html&gt;
          &lt;head&gt;
            &lt;title&gt;\{title}&lt;/title&gt;
          &lt;/head&gt;
          &lt;body&gt;
            &lt;p&gt;\{text}&lt;/p&gt;
          &lt;/body&gt;
        &lt;/html&gt;
        """</span><span class="o">;</span>
</code></pre></div></div>

<h4 id="template-processors">Template Processors</h4>

<p><code class="language-plaintext highlighter-rouge">STR</code> is a template processor defined in the Java Platform. It performs string interpolation by replacing each embedded expression in the template with the (stringified) value of that expression. It is a <code class="language-plaintext highlighter-rouge">public static final</code> field that is automatically imported into every Java source file.</p>

<p>More template processors exist:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">FMT</code> - besides performing interpolation, it also interprets format specifiers which appear to the left of embedded expressions. The format specifiers are the same as those defined in <code class="language-plaintext highlighter-rouge">java.util.Formatter</code>.</li>
  <li><code class="language-plaintext highlighter-rouge">RAW</code> - a standard template processor that produces an unprocessed <code class="language-plaintext highlighter-rouge">StringTemplate</code> object.</li>
</ul>

<h4 id="ensuring-safety">Ensuring Safety</h4>

<p>The construct <code class="language-plaintext highlighter-rouge">STR."..."</code> we’ve used so far is actually a short way to define a template and call its <code class="language-plaintext highlighter-rouge">process</code> method. That means that our first code example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">guitarType</span> <span class="o">=</span> <span class="s">"Les Paul"</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">STR</span><span class="o">.</span><span class="s">"I bought a \{guitarType} yesterday."</span><span class="o">);</span>
</code></pre></div></div>

<p>is equivalent to:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">guitarType</span> <span class="o">=</span> <span class="s">"Les Paul"</span><span class="o">;</span>
<span class="nc">StringTemplate</span> <span class="n">template</span> <span class="o">=</span> <span class="no">RAW</span><span class="o">.</span><span class="s">"I bought a \{guitarType} yesterday."</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">STR</span><span class="o">.</span><span class="na">process</span><span class="o">(</span><span class="n">template</span><span class="o">));</span>
</code></pre></div></div>

<p>Template expressions are designed to prevent the direct conversion of strings with embedded expressions to interpolated strings. This makes it impossible for potentially incorrect strings to spread. A template processor securely handles this interpolation, and if you forget to use one, the compiler will report an error.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">guitarType</span> <span class="o">=</span> <span class="s">"Les Paul"</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"I bought a \{guitarType} yesterday."</span><span class="o">);</span> <span class="c1">// doesn't compile!</span>
<span class="c1">// outputs: "error: processor missing from template expression"</span>
</code></pre></div></div>

<h4 id="custom-template-processors">Custom Template Processors</h4>

<p>Each template processor is an object that implements the functional interface <code class="language-plaintext highlighter-rouge">StringTemplate.Processor</code>, which means developers can easily create custom template processors. Custom template processors can make use of the methods <code class="language-plaintext highlighter-rouge">StringTemplate::fragments</code> and <code class="language-plaintext highlighter-rouge">StringTemplate::values</code> in order to use static fragments and dynamic values of the string template, respectively.</p>

<p>Custom template processors can be useful for various use cases. Let’s illustrate two of them with a few code examples:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="no">JSON</span> <span class="o">=</span> <span class="nc">StringTemplate</span><span class="o">.</span><span class="na">Processor</span><span class="o">.</span><span class="na">of</span><span class="o">(</span>
    <span class="o">(</span><span class="nc">StringTemplate</span> <span class="n">st</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nc">JSONObject</span><span class="o">(</span><span class="n">st</span><span class="o">.</span><span class="na">interpolate</span><span class="o">())</span>
<span class="o">);</span>

<span class="nc">String</span> <span class="n">name</span> <span class="o">=</span> <span class="s">"Gibson Les Paul Standard '50s Heritage Cherry Sunburst"</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">type</span> <span class="o">=</span> <span class="s">"Les Paul"</span><span class="o">;</span>
<span class="nc">JSONObject</span> <span class="n">doc</span> <span class="o">=</span> <span class="no">JSON</span><span class="o">.</span><span class="s">"""
    {
        "</span><span class="n">name</span><span class="s">": "</span><span class="err">\</span><span class="o">{</span><span class="n">name</span><span class="o">}</span><span class="s">",
        "</span><span class="n">type</span><span class="s">": "</span><span class="err">\</span><span class="o">{</span><span class="n">type</span><span class="o">}</span><span class="s">"
    };
    """</span><span class="o">;</span>
</code></pre></div></div>

<p>So the <code class="language-plaintext highlighter-rouge">JSON</code> template processor returns instances of <code class="language-plaintext highlighter-rouge">JSONObject</code> instead of <code class="language-plaintext highlighter-rouge">String</code>.
If we wanted, we could simply add more validation logic to the implementation of <code class="language-plaintext highlighter-rouge">JSON</code> to make the template processor handles its parameters a bit more safely.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">record</span> <span class="nf">QueryBuilder</span><span class="o">(</span><span class="nc">Connection</span> <span class="n">conn</span><span class="o">)</span> <span class="kd">implements</span> <span class="nc">StringTemplate</span><span class="o">.</span><span class="na">Processor</span><span class="o">&lt;</span><span class="nc">PreparedStatement</span><span class="o">,</span> <span class="nc">SQLException</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="nc">PreparedStatement</span> <span class="nf">process</span><span class="o">(</span><span class="nc">StringTemplate</span> <span class="n">st</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">SQLException</span> <span class="o">{</span>
        <span class="c1">// 1. Replace StringTemplate placeholders with PreparedStatement placeholders</span>
        <span class="nc">String</span> <span class="n">query</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">join</span><span class="o">(</span><span class="s">"?"</span><span class="o">,</span> <span class="n">st</span><span class="o">.</span><span class="na">fragments</span><span class="o">());</span>

        <span class="c1">// 2. Create the PreparedStatement on the connection</span>
        <span class="nc">PreparedStatement</span> <span class="n">ps</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="na">prepareStatement</span><span class="o">(</span><span class="n">query</span><span class="o">);</span>

        <span class="c1">// 3. Set parameters of the PreparedStatement</span>
        <span class="kt">int</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">1</span><span class="o">;</span>
        <span class="k">for</span> <span class="o">(</span><span class="nc">Object</span> <span class="n">value</span> <span class="o">:</span> <span class="n">st</span><span class="o">.</span><span class="na">values</span><span class="o">())</span> <span class="o">{</span>
            <span class="k">switch</span> <span class="o">(</span><span class="n">value</span><span class="o">)</span> <span class="o">{</span>
                <span class="k">case</span> <span class="nc">Integer</span> <span class="n">i</span> <span class="o">-&gt;</span> <span class="n">ps</span><span class="o">.</span><span class="na">setInt</span><span class="o">(</span><span class="n">index</span><span class="o">++,</span> <span class="n">i</span><span class="o">);</span>
                <span class="k">case</span> <span class="nc">Float</span> <span class="n">f</span>   <span class="o">-&gt;</span> <span class="n">ps</span><span class="o">.</span><span class="na">setFloat</span><span class="o">(</span><span class="n">index</span><span class="o">++,</span> <span class="n">f</span><span class="o">);</span>
                <span class="k">case</span> <span class="nc">Double</span> <span class="n">d</span>  <span class="o">-&gt;</span> <span class="n">ps</span><span class="o">.</span><span class="na">setDouble</span><span class="o">(</span><span class="n">index</span><span class="o">++,</span> <span class="n">d</span><span class="o">);</span>
                <span class="k">case</span> <span class="nc">Boolean</span> <span class="n">b</span> <span class="o">-&gt;</span> <span class="n">ps</span><span class="o">.</span><span class="na">setBoolean</span><span class="o">(</span><span class="n">index</span><span class="o">++,</span> <span class="n">b</span><span class="o">);</span>
                <span class="k">default</span>        <span class="o">-&gt;</span> <span class="n">ps</span><span class="o">.</span><span class="na">setString</span><span class="o">(</span><span class="n">index</span><span class="o">++,</span> <span class="nc">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="n">value</span><span class="o">));</span>
            <span class="o">}</span>
        <span class="o">}</span>

        <span class="k">return</span> <span class="n">ps</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="no">DB</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">QueryBuilder</span><span class="o">(</span><span class="n">conn</span><span class="o">);</span>
<span class="nc">String</span> <span class="n">type</span> <span class="o">=</span> <span class="s">"Les Paul"</span><span class="o">;</span> 
<span class="nc">PreparedStatement</span> <span class="n">ps</span> <span class="o">=</span> <span class="no">DB</span><span class="o">.</span><span class="s">"SELECT * FROM Guitar g WHERE g.guitar_type = \{type}"</span><span class="o">;</span>
<span class="nc">ResultSet</span> <span class="n">rs</span> <span class="o">=</span> <span class="n">ps</span><span class="o">.</span><span class="na">executeQuery</span><span class="o">();</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">DB</code> custom template processor is capable of constructing <code class="language-plaintext highlighter-rouge">PreparedStatements</code> that have their parameters injected in a safe way.</p>

<h4 id="whats-different-from-java-20-4">What’s Different From Java 20?</h4>

<p>Java 20 didn’t contain anything related to string templates yet, so Java 21 is the first time we get to experiment with them. Note that the JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to be able to take the feature for a spin.</p>

<h4 id="more-information-4">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/430">JEP 430</a>.</p>

<h2 id="from-project-loom">From Project Loom</h2>

<p>Java 21 contains three features that originated from <a href="http://openjdk.java.net/projects/loom/">Project Loom</a>:</p>

<ul>
  <li>Virtual Threads;</li>
  <li>Structured Concurrency.</li>
  <li>Scoped Values;</li>
</ul>

<blockquote>
  <p>Project Loom strives to simplify maintaining concurrent applications in Java by introducing <em>virtual threads</em> and an API for <em>structured concurrency</em>, among other things.</p>
</blockquote>

<h3 id="jep-444-virtual-threads">JEP 444: Virtual Threads</h3>

<p>Threads have been a part of Java since the very beginning, and since the start of Project Loom we gradually started calling them ‘platform threads’ instead. A platform thread runs Java code on an underlying OS thread and captures the OS thread for the code’s entire lifetime. The number of platform threads is therefore limited to the number of available OS threads.</p>

<p>Modern applications, however, might need many more threads than that; when dealing with tens of thousands of requests at the same time, for example. This is where <em>virtual threads</em> come in. A virtual thread is an instance of <code class="language-plaintext highlighter-rouge">java.lang.Thread</code> that also runs Java code on an underlying OS thread, but does not capture the OS thread for the code’s entire lifetime. This means that many virtual threads can run their Java code on the same OS thread, effectively sharing it. The number of virtual threads can thus be much larger than the number of available OS threads.</p>

<p>Aside from being plentiful, virtual threads are also cheap to create and dispose of. This means that a web framework, for example, can dedicate a new virtual thread to the task of handling a request and still be able to process thousands or even millions of requests at once.</p>

<h4 id="typical-use-cases">Typical Use Cases</h4>

<p>Using virtual threads does not require learning new concepts, though it may require unlearning habits developed to cope with today’s high cost of threads. Virtual threads will not only help application developers; they will also help framework designers provide easy-to-use APIs that are compatible with the platform’s design without compromising on scalability.</p>

<h4 id="creating-virtual-threads">Creating Virtual Threads</h4>

<p>Just like a platform thread, a virtual thread is an instance of <code class="language-plaintext highlighter-rouge">java.lang.Thread</code>. So you can use a virtual thread in exactly the same way as a platform thread.</p>

<p>Creating a virtual thread is a bit different from creating a platform thread, but just as easy:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">platformThread</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Thread</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="o">{</span>
    <span class="c1">// do some work in a platform thread</span>
<span class="o">});</span>
<span class="n">platformThread</span><span class="o">.</span><span class="na">start</span><span class="o">();</span>

<span class="kt">var</span> <span class="n">virtualThread</span> <span class="o">=</span> <span class="nc">Thread</span><span class="o">.</span><span class="na">startVirtualThread</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="o">{</span>
    <span class="c1">// do some work in a virtual thread</span>
<span class="o">});</span>
</code></pre></div></div>

<p>When your code uses the <code class="language-plaintext highlighter-rouge">ExecutorService</code> interface already, switching to virtual threads will take even less effort:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">platformThreadsExecutor</span> <span class="o">=</span> <span class="nc">Executors</span><span class="o">.</span><span class="na">newCachedThreadPool</span><span class="o">();</span>
<span class="n">platformThreadsExecutor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="o">{</span>
    <span class="c1">// do some work in a platform thread</span>
<span class="o">});</span>
<span class="n">platformThreadsExecutor</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>

<span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">virtualThreadsExecutor</span> <span class="o">=</span> <span class="nc">Executors</span><span class="o">.</span><span class="na">newVirtualThreadPerTaskExecutor</span><span class="o">())</span> <span class="o">{</span>
    <span class="n">virtualThreadsExecutor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="o">{</span>
        <span class="c1">// do some work in a virtual thread</span>
    <span class="o">});</span>
<span class="o">}</span> <span class="c1">// close() is called implicitly</span>
</code></pre></div></div>

<p>Note that the <code class="language-plaintext highlighter-rouge">ExecutorService</code> interface was adjusted in Java 19 to extend <code class="language-plaintext highlighter-rouge">AutoCloseable</code>, so it can now be used in a try-with-resources construct.</p>

<h4 id="thread-dump-mechanism">Thread Dump Mechanism</h4>

<p>A new kind of thread dump in <code class="language-plaintext highlighter-rouge">jcmd</code> was introduced to present virtual threads alongside platform threads, all grouped in a meaningful way. This new way of presenting threads was needed, because of the way the JDK’s traditional thread dump (obtained through <code class="language-plaintext highlighter-rouge">jstack</code> or <code class="language-plaintext highlighter-rouge">jcmd</code>) presents a flat list of threads. The old format worked fine with hundreds of platform threads, but it is unsuitable for thousands or millions of virtual threads. An additional benefit of the new thread dump is the ability to show richer relationships amoung threads when programs use <a href="#jep-453-structured-concurrency-preview">structured concurrency</a>.</p>

<h4 id="whats-different-from-java-20-5">What’s Different From Java 20?</h4>

<p>Based on developer feedback the following changes were made to virtual threads compared to Java 20:</p>

<ul>
  <li>Virtual threads now always support thread-local variables. Guaranteed support for thread-local variables ensures that many more existing libraries can be used unchanged with virtual threads, and this helps with the migration of task-oriented code to use virtual threads.</li>
  <li>Virtual threads created directly with the Thread.Builder API (as opposed to those created through <code class="language-plaintext highlighter-rouge">Executors.newVirtualThreadPerTaskExecutor()</code>) are now also, by default, monitored throughout their lifetime and observable via the new thread dump mechanism.</li>
</ul>

<h4 id="more-information-5">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/444">JEP 444</a>.</p>

<h3 id="jep-453-structured-concurrency-preview">JEP 453: Structured Concurrency (Preview)</h3>

<p>Java’s current implementation of concurrency is <em>unstructured</em>, meaning that tasks run independently of each other. They don’t come with any hierarchy, scope, or other structure, which means they cannot easily pass errors or cancellation intent to each other.
To illustrate this, let’s look at a code example that takes place in a restaurant:</p>

<blockquote>
  <p>All code examples that illustrate Structured Concurrency were taken from my conference talk <a href="https://hanno.codes/talks/#javas-concurrency-journey-continues">“Java’s Concurrency Journey Continues! Exploring Structured Concurrency and Scoped Values”</a>.</p>
</blockquote>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">MultiWaiterRestaurant</span> <span class="kd">implements</span> <span class="nc">Restaurant</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">MultiCourseMeal</span> <span class="nf">announceMenu</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">ExecutionException</span><span class="o">,</span> <span class="nc">InterruptedException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">grover</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Grover"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">rosita</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Rosita"</span><span class="o">);</span>

        <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">executor</span> <span class="o">=</span> <span class="nc">Executors</span><span class="o">.</span><span class="na">newVirtualThreadPerTaskExecutor</span><span class="o">())</span> <span class="o">{</span>
            <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">starter</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">grover</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">STARTER</span><span class="o">));</span>
            <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">main</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">MAIN</span><span class="o">));</span>
            <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">dessert</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">rosita</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">DESSERT</span><span class="o">));</span>

            <span class="k">return</span> <span class="k">new</span> <span class="nf">MultiCourseMeal</span><span class="o">(</span><span class="n">starter</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">main</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">dessert</span><span class="o">.</span><span class="na">get</span><span class="o">());</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Now, consider the fact that the <code class="language-plaintext highlighter-rouge">announceCourse(..)</code> method in the <code class="language-plaintext highlighter-rouge">Waiter</code> class sometimes fails with an <code class="language-plaintext highlighter-rouge">OutOfStockException</code>, because one of the ingredients for the course might not be in stock. This can lead to some problems:</p>

<ul>
  <li>If <code class="language-plaintext highlighter-rouge">zoe.announceCourse(CourseType.MAIN)</code> takes a long time to execute but <code class="language-plaintext highlighter-rouge">grover.announceCourse(CourseType.STARTER)</code> fails in the meantime, the <code class="language-plaintext highlighter-rouge">announceMenu(..)</code> method will unnecessarily wait for the main course announcement by blocking on <code class="language-plaintext highlighter-rouge">main.get()</code>, instead of cancelling it (which would be the sensible thing to do).</li>
  <li>If an exception happens in <code class="language-plaintext highlighter-rouge">zoe.announceCourse(CourseType.MAIN)</code>, <code class="language-plaintext highlighter-rouge">main.get()</code> will throw it, but <code class="language-plaintext highlighter-rouge">grover.announceCourse(CourseType.STARTER)</code> will continue to run in its own thread, resulting in thread leakage.</li>
  <li>If the thread executing <code class="language-plaintext highlighter-rouge">announceMenu(..)</code> is interrupted, the interruption will not propagate to the subtasks: all threads that run an <code class="language-plaintext highlighter-rouge">announceCourse(..)</code> invocation will leak, continuing to run even after <code class="language-plaintext highlighter-rouge">announceMenu()</code> has failed.</li>
</ul>

<p>Ultimately the problem here is that our program is logically structured with task-subtask relationships, but these relationships exist only in the mind of the developer. We might all prefer structured code that reads like a sequential story, but this example simply doesn’t meet that criterion.</p>

<p>In contrast, the execution of single-threaded code <em>always</em> enforces a hierarchy of tasks and subtasks. Consider the following single-threaded version of our restaurant example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">SingleWaiterRestaurant</span> <span class="kd">implements</span> <span class="nc">Restaurant</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">MultiCourseMeal</span> <span class="nf">announceMenu</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">OutOfStockException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">elmo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Elmo"</span><span class="o">);</span>

        <span class="nc">Course</span> <span class="n">starter</span> <span class="o">=</span> <span class="n">elmo</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">STARTER</span><span class="o">);</span>
        <span class="nc">Course</span> <span class="n">main</span> <span class="o">=</span> <span class="n">elmo</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">MAIN</span><span class="o">);</span>
        <span class="nc">Course</span> <span class="n">dessert</span> <span class="o">=</span> <span class="n">elmo</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">DESSERT</span><span class="o">);</span>

        <span class="k">return</span> <span class="k">new</span> <span class="nf">MultiCourseMeal</span><span class="o">(</span><span class="n">starter</span><span class="o">,</span> <span class="n">main</span><span class="o">,</span> <span class="n">dessert</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here, we don’t have <em>any</em> of the problems we had before.
Our waiter Elmo will announce the courses in exactly the right order, and if one subtask fails the remaining one(s) won’t even be started.
And because all work runs in the same thread, there is no risk of thread leakage.</p>

<p>So from these two examples it is evident that concurrent programming would be a lot easier and more intuitive if it would be able to enforce the hierarchy of tasks and subtasks, just like single-threaded code can.</p>

<h4 id="introducing-structured-concurrency">Introducing Structured Concurrency</h4>

<p>In a structured concurrency approach, threads have a clear hierarchy, their own scope, and clear entry and exit points. Structured concurrency arranges threads hierarchically, akin to function calls, forming a tree with parent-child relationships. Execution scopes persist until all child threads complete, matching code structure.</p>

<h4 id="shutdown-on-failure">Shutdown on Failure</h4>

<p>Let’s now take a look at a structured, concurrent version of our example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">StructuredConcurrencyRestaurant</span> <span class="kd">implements</span> <span class="nc">Restaurant</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">MultiCourseMeal</span> <span class="nf">announceMenu</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">ExecutionException</span><span class="o">,</span> <span class="nc">InterruptedException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">grover</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Grover"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">rosita</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Rosita"</span><span class="o">);</span>

        <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">scope</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StructuredTaskScope</span><span class="o">.</span><span class="na">ShutdownOnFailure</span><span class="o">())</span> <span class="o">{</span>
            <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">starter</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">grover</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">STARTER</span><span class="o">));</span>
            <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">main</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">MAIN</span><span class="o">));</span>
            <span class="nc">Supplier</span><span class="o">&lt;</span><span class="nc">Course</span><span class="o">&gt;</span> <span class="n">dessert</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">rosita</span><span class="o">.</span><span class="na">announceCourse</span><span class="o">(</span><span class="nc">CourseType</span><span class="o">.</span><span class="na">DESSERT</span><span class="o">));</span>

            <span class="n">scope</span><span class="o">.</span><span class="na">join</span><span class="o">();</span> <span class="c1">// 1</span>
            <span class="n">scope</span><span class="o">.</span><span class="na">throwIfFailed</span><span class="o">();</span> <span class="c1">// 2</span>

            <span class="k">return</span> <span class="k">new</span> <span class="nf">MultiCourseMeal</span><span class="o">(</span><span class="n">starter</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">main</span><span class="o">.</span><span class="na">get</span><span class="o">(),</span> <span class="n">dessert</span><span class="o">.</span><span class="na">get</span><span class="o">());</span> <span class="c1">// 3</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>The scope’s purpose is to keep the threads together.
At <code class="language-plaintext highlighter-rouge">1</code>, we wait (<code class="language-plaintext highlighter-rouge">join</code>) until <em>all</em> threads are done with their work. 
If one of the threads is interrupted, an <code class="language-plaintext highlighter-rouge">InterruptedException</code> is thrown here. 
At <code class="language-plaintext highlighter-rouge">2</code>, an <code class="language-plaintext highlighter-rouge">ExecutionException</code> can be thrown if an exception occurs in one of the threads. 
Once we reach <code class="language-plaintext highlighter-rouge">3</code>, we can be sure everything has gone well, and we can retrieve and process the results.</p>

<p>Actually, the main difference with the code we had before is the fact that we create threads (<code class="language-plaintext highlighter-rouge">fork</code>) within a new <code class="language-plaintext highlighter-rouge">scope</code>. 
Now we can be certain that the lifetimes of the three threads are confined to this scope, which coincides with the body of the try-with-resources statement.</p>

<p>Furthermore, we’ve gained <em>short-circuiting behaviour</em>. 
When one of the <code class="language-plaintext highlighter-rouge">announceCourse(..)</code> subtasks fails, the others are cancelled if they have not completed yet.
This behaviour is managed by the <code class="language-plaintext highlighter-rouge">ShutdownOnFailure</code> policy.
We’ve also gained <em>cancellation propagation</em>.
When the thread that runs <code class="language-plaintext highlighter-rouge">announceMenu()</code> is interrupted before or during the call to <code class="language-plaintext highlighter-rouge">scope.join()</code>, all subtasks are cancelled automatically when the thread exits the scope.</p>

<h4 id="shutdown-on-success">Shutdown on Success</h4>

<p>A shutdown-on-failure policy cancels tasks if one of them fails, while a <em>shutdown-on-success</em> policy cancels tasks if one succeeds. The latter is useful to prevent unnecessary work once a successful result is obtained.</p>

<p>Let’s see what a shutdown-on-success implementation would look like:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="n">record</span> <span class="nf">DrinkOrder</span><span class="o">(</span><span class="nc">Guest</span> <span class="n">guest</span><span class="o">,</span> <span class="nc">Drink</span> <span class="n">drink</span><span class="o">)</span> <span class="o">{}</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">StructuredConcurrencyBar</span> <span class="kd">implements</span> <span class="nc">Bar</span> <span class="o">{</span>
    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="nc">DrinkOrder</span> <span class="nf">determineDrinkOrder</span><span class="o">(</span><span class="nc">Guest</span> <span class="n">guest</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">InterruptedException</span><span class="o">,</span> <span class="nc">ExecutionException</span> <span class="o">{</span>
        <span class="nc">Waiter</span> <span class="n">zoe</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Zoe"</span><span class="o">);</span>
        <span class="nc">Waiter</span> <span class="n">elmo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Waiter</span><span class="o">(</span><span class="s">"Elmo"</span><span class="o">);</span>

        <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">scope</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StructuredTaskScope</span><span class="o">.</span><span class="na">ShutdownOnSuccess</span><span class="o">&lt;</span><span class="nc">DrinkOrder</span><span class="o">&gt;())</span> <span class="o">{</span>
            <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">zoe</span><span class="o">.</span><span class="na">getDrinkOrder</span><span class="o">(</span><span class="n">guest</span><span class="o">,</span> <span class="no">BEER</span><span class="o">,</span> <span class="no">WINE</span><span class="o">,</span> <span class="no">JUICE</span><span class="o">));</span>
            <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">elmo</span><span class="o">.</span><span class="na">getDrinkOrder</span><span class="o">(</span><span class="n">guest</span><span class="o">,</span> <span class="no">COFFEE</span><span class="o">,</span> <span class="no">TEA</span><span class="o">,</span> <span class="no">COCKTAIL</span><span class="o">,</span> <span class="no">DISTILLED</span><span class="o">));</span>

            <span class="k">return</span> <span class="n">scope</span><span class="o">.</span><span class="na">join</span><span class="o">().</span><span class="na">result</span><span class="o">();</span> <span class="c1">// 1</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>In this example the waiter is responsible for getting a valid <code class="language-plaintext highlighter-rouge">DrinkOrder</code> object based on the preferences of the guest and the current supply of drinks at the bar.
After the method <code class="language-plaintext highlighter-rouge">Waiter.getDrinkOrder(Guest guest, DrinkCategory... categories)</code> has been called, the waiter starts to list all available drinks in the drink categories that were passed to the method.
Once a guest hears something they like, they respond and the waiter creates a drink order. When this happens, the <code class="language-plaintext highlighter-rouge">getDrinkOrder(..)</code> method returns a <code class="language-plaintext highlighter-rouge">DrinkOrder</code> object and the scope will shut down. 
This means that any unfinished subtasks (such as the one in which Elmo is still listing different kinds of tea) will be cancelled.
The <code class="language-plaintext highlighter-rouge">result()</code> method at <code class="language-plaintext highlighter-rouge">1</code> will either return a valid <code class="language-plaintext highlighter-rouge">DrinkOrder</code> object, or throw an <code class="language-plaintext highlighter-rouge">ExecutionException</code> if one of the subtasks has failed.</p>

<h4 id="custom-shutdown-policies">Custom Shutdown Policies</h4>

<p>Two shutdown policies are provided out-of-the-box, but it’s also possible to create your own by extending the class <code class="language-plaintext highlighter-rouge">StructuredTaskScope</code> and its protected <code class="language-plaintext highlighter-rouge">handleComplete(..)</code> method.
That will allow you to have full control over when the scope will shut down and what results will be collected.</p>

<h4 id="whats-different-from-java-20-6">What’s Different From Java 20?</h4>

<p>The situation is roughly the same as how it was in Java 20 (see <a href="https://openjdk.org/jeps/437">JEP 437</a>), except for two minor changes:</p>

<ul>
  <li>Structured Concurrency is now a Preview API;</li>
  <li>The <code class="language-plaintext highlighter-rouge">StructuredTaskScope::fork</code> method now returns a <code class="language-plaintext highlighter-rouge">Subtask</code> instead of a <code class="language-plaintext highlighter-rouge">Future</code> (<a href="https://openjdk.org/jeps/453#Why-doesn't-fork----return-a-Future?">why?</a>).</li>
</ul>

<p>Note that the JEP is in the <a href="https://openjdk.org/jeps/12">preview</a> stage, so you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to be able to take the feature for a spin.</p>

<h4 id="more-information-6">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/453">JEP 453</a>. Or if you want to try out structured concurrency and you liked the code examples, then here’s a <a href="https://github.com/hannotify/structured-concurrency-bar">GitHub repository</a> to get you started.</p>

<h3 id="jep-446-scoped-values-preview">JEP 446: Scoped Values (Preview)</h3>

<p><em>Scoped values</em> 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.</p>

<h4 id="threadlocal">ThreadLocal</h4>

<p>Since Java 1.2 we can make use of <code class="language-plaintext highlighter-rouge">ThreadLocal</code> variables, which confine a certain value to the thread that created it. Back then it could be a simple way to achieve thread-safety, <a href="https://stackoverflow.com/a/817926">in some cases</a>.</p>

<p>But thread-local variables also come with a few caveats. Every thread-local variable is mutable, which makes it hard to discern which component updates shared state and in what order. There’s also the risk of memory leaks, because unless you call <code class="language-plaintext highlighter-rouge">remove()</code> on the <code class="language-plaintext highlighter-rouge">ThreadLocal</code> the data is retained until it is garbage collected (which is only after the thread terminates). And finally, thread-local variables of a parent thread can be inherited by child threads, which results in the child thread having to allocate storage for every thread-local variable previously written in the parent thread.</p>

<p>These drawbacks become more apparent now that virtual threads have been introduced, because millions of them could be active at the same time - each with their own thread-local variables - which would result in a significant memory footprint.</p>

<h4 id="scoped-values">Scoped Values</h4>

<p>Like a thread-local variable, a scoped value has multiple incarnations, one per thread. Unlike a thread-local variable, a scoped value is written once and is then immutable, and is available only for a bounded period during execution of the thread.</p>

<p>The JEP illustrates the use of scoped values with the pseudo code example below:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">final</span> <span class="kd">static</span> <span class="nc">ScopedValue</span><span class="o">&lt;...&gt;</span> <span class="no">V</span> <span class="o">=</span> <span class="nc">ScopedValue</span><span class="o">.</span><span class="na">newInstance</span><span class="o">();</span>

<span class="c1">// In some method</span>
<span class="nc">ScopedValue</span><span class="o">.</span><span class="na">where</span><span class="o">(</span><span class="no">V</span><span class="o">,</span> <span class="o">&lt;</span><span class="n">value</span><span class="o">&gt;)</span>
           <span class="o">.</span><span class="na">run</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="o">{</span> <span class="o">...</span> <span class="no">V</span><span class="o">.</span><span class="na">get</span><span class="o">()</span> <span class="o">...</span> <span class="n">call</span> <span class="n">methods</span> <span class="o">...</span> <span class="o">});</span>

<span class="c1">// In a method called directly or indirectly from the lambda expression</span>
<span class="o">...</span> <span class="no">V</span><span class="o">.</span><span class="na">get</span><span class="o">()</span> <span class="o">...</span>
</code></pre></div></div>

<p>We see that <code class="language-plaintext highlighter-rouge">ScopedValue.where(...)</code> is called, presenting a scoped value and the object to which it is to be bound. The call to <code class="language-plaintext highlighter-rouge">run(...)</code> binds the scoped value, providing an incarnation that is specific to the current thread, and then executes the lambda expression passed as argument. During the lifetime of the <code class="language-plaintext highlighter-rouge">run(...)</code> call, the lambda expression, or any method called directly or indirectly from that expression, can read the scoped value via the value’s <code class="language-plaintext highlighter-rouge">get()</code> method. After the <code class="language-plaintext highlighter-rouge">run(...)</code> method finishes, the binding is destroyed.</p>

<h4 id="typical-use-cases-1">Typical Use Cases</h4>

<p>Scoped values will be useful in all places where currently thread-local variables are used for the purpose of one-way transmission of unchanging data.</p>

<h4 id="whats-different-from-java-20-7">What’s Different From Java 20?</h4>

<p>The only difference from Java 20 is that Scoped Values has become a Preview API in Java 21, which means you’ll need to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the command-line to be able to take the feature for a spin.</p>

<h4 id="more-information-7">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/446">JEP 446</a>.</p>

<h2 id="from-project-panama">From Project Panama</h2>

<p>Java 21 contains two features that originated from <a href="http://openjdk.java.net/projects/panama/">Project Panama</a>:</p>

<ul>
  <li>Foreign Function &amp; Memory API;</li>
  <li>Vector API.</li>
</ul>

<blockquote>
  <p>Project Panama aims to improve the connection between the JVM and foreign (non-Java) libraries.</p>
</blockquote>

<h3 id="jep-442-foreign-function--memory-api-third-preview">JEP 442: Foreign Function &amp; Memory API (Third Preview)</h3>

<p>Java programs have always had the option of interacting with code and data outside of the Java runtime, through the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jni/">Java Native Interface</a> (JNI).
And accessing foreign memory (outside of the JVM, so off-heap) was possible using either the <a href="https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/nio/ByteBuffer.html">ByteBuffer API</a> or the <a href="https://github.com/openjdk/jdk/blob/master/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java">sun.misc.Unsafe API</a>.</p>

<p>However, all these mechanisms have downsides, which is why a more modern API is now proposed to support foreign functions and foreign memory in a better way.</p>

<blockquote>
  <p>Performance-critical libraries like <a href="https://github.com/tensorflow/tensorflow">Tensorflow</a>, <a href="https://lucene.apache.org/">Lucene</a> or <a href="https://netty.io/">Netty</a> typically rely on using foreign memory, because they need more control over the memory they use to prevent the cost and unpredictability that comes with garbage collection.</p>
</blockquote>

<h4 id="code-example">Code Example</h4>

<p>In order to demonstrate the new API, <a href="https://openjdk.org/jeps/442">JEP 442</a> lists a code example that obtains a method handle for a C library function <code class="language-plaintext highlighter-rouge">radixsort</code> and then uses it to sort four strings that start out as Java array elements:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// 1. Find foreign function on the C library path</span>
<span class="nc">Linker</span> <span class="n">linker</span>          <span class="o">=</span> <span class="nc">Linker</span><span class="o">.</span><span class="na">nativeLinker</span><span class="o">();</span>
<span class="nc">SymbolLookup</span> <span class="n">stdlib</span>    <span class="o">=</span> <span class="n">linker</span><span class="o">.</span><span class="na">defaultLookup</span><span class="o">();</span>
<span class="nc">MethodHandle</span> <span class="n">radixsort</span> <span class="o">=</span> <span class="n">linker</span><span class="o">.</span><span class="na">downcallHandle</span><span class="o">(</span><span class="n">stdlib</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="s">"radixsort"</span><span class="o">),</span> <span class="o">...);</span>
<span class="c1">// 2. Allocate on-heap memory to store four strings</span>
<span class="nc">String</span><span class="o">[]</span> <span class="n">javaStrings</span> <span class="o">=</span> <span class="o">{</span> <span class="s">"mouse"</span><span class="o">,</span> <span class="s">"cat"</span><span class="o">,</span> <span class="s">"dog"</span><span class="o">,</span> <span class="s">"car"</span> <span class="o">};</span>
<span class="c1">// 3. Use try-with-resources to manage the lifetime of off-heap memory</span>
<span class="k">try</span> <span class="o">(</span><span class="nc">Arena</span> <span class="n">offHeap</span> <span class="o">=</span> <span class="nc">Arena</span><span class="o">.</span><span class="na">ofConfined</span><span class="o">())</span> <span class="o">{</span>
    <span class="c1">// 4. Allocate a region of off-heap memory to store four pointers</span>
    <span class="nc">MemorySegment</span> <span class="n">pointers</span> <span class="o">=</span> <span class="n">offHeap</span><span class="o">.</span><span class="na">allocateArray</span><span class="o">(</span><span class="nc">ValueLayout</span><span class="o">.</span><span class="na">ADDRESS</span><span class="o">,</span> <span class="n">javaStrings</span><span class="o">.</span><span class="na">length</span><span class="o">);</span>
    <span class="c1">// 5. Copy the strings from on-heap to off-heap</span>
    <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">javaStrings</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="nc">MemorySegment</span> <span class="n">cString</span> <span class="o">=</span> <span class="n">offHeap</span><span class="o">.</span><span class="na">allocateUtf8String</span><span class="o">(</span><span class="n">javaStrings</span><span class="o">[</span><span class="n">i</span><span class="o">]);</span>
        <span class="n">pointers</span><span class="o">.</span><span class="na">setAtIndex</span><span class="o">(</span><span class="nc">ValueLayout</span><span class="o">.</span><span class="na">ADDRESS</span><span class="o">,</span> <span class="n">i</span><span class="o">,</span> <span class="n">cString</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="c1">// 6. Sort the off-heap data by calling the foreign function</span>
    <span class="n">radixsort</span><span class="o">.</span><span class="na">invoke</span><span class="o">(</span><span class="n">pointers</span><span class="o">,</span> <span class="n">javaStrings</span><span class="o">.</span><span class="na">length</span><span class="o">,</span> <span class="nc">MemorySegment</span><span class="o">.</span><span class="na">NULL</span><span class="o">,</span> <span class="sc">'\0'</span><span class="o">);</span>
    <span class="c1">// 7. Copy the (reordered) strings from off-heap to on-heap</span>
    <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">javaStrings</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="nc">MemorySegment</span> <span class="n">cString</span> <span class="o">=</span> <span class="n">pointers</span><span class="o">.</span><span class="na">getAtIndex</span><span class="o">(</span><span class="nc">ValueLayout</span><span class="o">.</span><span class="na">ADDRESS</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
        <span class="n">javaStrings</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="n">cString</span><span class="o">.</span><span class="na">getUtf8String</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span> <span class="c1">// 8. All off-heap memory is deallocated here</span>
<span class="k">assert</span> <span class="nc">Arrays</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">javaStrings</span><span class="o">,</span> <span class="k">new</span> <span class="nc">String</span><span class="o">[]</span> <span class="o">{</span><span class="s">"car"</span><span class="o">,</span> <span class="s">"cat"</span><span class="o">,</span> <span class="s">"dog"</span><span class="o">,</span> <span class="s">"mouse"</span><span class="o">});</span>  <span class="c1">// true</span>
</code></pre></div></div>

<p>Let’s look at some of the types this code uses in more detail to get a rough idea of their function and purpose within the Foreign Function &amp; Memory API:</p>

<dl>
  <dt><code class="language-plaintext highlighter-rouge">Linker</code></dt>
  <dd>Provides access to foreign functions from Java code, and access to Java code from foreign functions. It allows Java code to link against foreign functions, via <em>downcall method handles</em>. It also allows foreign functions to call Java method handles, via the generation of <em>upcall stubs</em>. See the <a href="https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/foreign/Linker.html">JavaDoc</a> of this type for more information.</dd>
  <dt><code class="language-plaintext highlighter-rouge">SymbolLookup</code></dt>
  <dd>Retrieves the address of a symbol in one or more libraries. See the <a href="https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/foreign/SymbolLookup.html">JavaDoc</a> of this type for more information.</dd>
  <dt><code class="language-plaintext highlighter-rouge">Arena</code></dt>
  <dd>Controls the lifecycle of memory segments. An arena has a scope, called the arena scope. When the arena is closed, the arena scope is no longer alive. As a result, all the segments associated with the arena scope are invalidated, their backing memory regions are deallocated (where applicable) and can no longer be accessed after the arena is closed. See the <a href="https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/foreign/Arena.html">JavaDoc</a> of this type for more information.</dd>
  <dt><code class="language-plaintext highlighter-rouge">MemorySegment</code></dt>
  <dd>Provides access to a contiguous region of memory. There are two kinds of memory segments: <em>heap segments</em> (inside the Java memory heap) and <em>native segments</em> (outside of the Java memory heap). See the <a href="https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/foreign/MemorySegment.html">JavaDoc</a> of this type for more information.</dd>
  <dt><code class="language-plaintext highlighter-rouge">ValueLayout</code></dt>
  <dd>Models values of basic data types, such as <em>integral</em> values, <em>floating-point</em> values and <em>address</em> values. On top of that, it defines useful value layout constants for Java primitive types and addresses. See the <a href="https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/foreign/ValueLayout.html">JavaDoc</a> of this type for more information.</dd>
</dl>

<h4 id="whats-different-from-java-20-8">What’s Different From Java 20?</h4>

<p>In Java 20, this feature was in second preview (in the form of <a href="https://openjdk.org/jeps/434">JEP 434</a>) to gather more developer feedback. Based on this feedback the following changes happened in Java 21:</p>

<ul>
  <li>Lifetimes management of native segments in the <code class="language-plaintext highlighter-rouge">Arena</code> interface is now centralized;</li>
  <li>Layout paths with a new element to dereference address layouts have been enhanced;</li>
  <li>A linker option to optimize calls to functions that are short-lived and will not upcall to Java has been provided;</li>
  <li>A fallback native linker implementation has been provided, to facilitate porting;</li>
  <li>The <code class="language-plaintext highlighter-rouge">VaList</code> class has been removed.</li>
</ul>

<h4 id="more-information-8">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/442">JEP 442</a>.</p>

<h3 id="jep-448-vector-api-sixth-incubator">JEP 448: Vector API (Sixth Incubator)</h3>

<p>The Vector API makes it possible to express vector computations that reliably compile at runtime to optimal vector instructions. 
This means that these computations will significantly outperform equivalent scalar computations on the supported CPU architectures (x64 and AArch64).</p>

<h4 id="vector-computations-help-me-out-here">Vector Computations? Help Me Out Here!</h4>

<p>A <em>vector computation</em> is a mathematical operation on one or more one-dimensional matrices of an arbitrary length. Think of a vector as an array with a dynamic length. Furthermore, the elements in the vector can be accessed in constant time via indices, just like with an array.</p>

<p>In the past, Java programmers could only program such computations at the assembly-code level. But now that modern CPUs support advanced <a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">SIMD</a> features (Single Instruction, Multiple Data), it becomes more important to take advantage of the performance gains that SIMD instructions and multiple lanes operating in parallel can bring. The Vector API brings that possibility closer to the Java programmer.</p>

<h4 id="code-example-1">Code Example</h4>

<p>Here is a code example (taken from the JEP) that compares a simple scalar computation over elements of arrays with its equivalent using the Vector API:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">scalarComputation</span><span class="o">(</span><span class="kt">float</span><span class="o">[]</span> <span class="n">a</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">b</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">c</span><span class="o">)</span> <span class="o">{</span>
   <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="n">c</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">+</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">])</span> <span class="o">*</span> <span class="o">-</span><span class="mf">1.0f</span><span class="o">;</span>
   <span class="o">}</span>
<span class="o">}</span>

<span class="kd">static</span> <span class="kd">final</span> <span class="nc">VectorSpecies</span><span class="o">&lt;</span><span class="nc">Float</span><span class="o">&gt;</span> <span class="no">SPECIES</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">SPECIES_PREFERRED</span><span class="o">;</span>

<span class="kt">void</span> <span class="nf">vectorComputation</span><span class="o">(</span><span class="kt">float</span><span class="o">[]</span> <span class="n">a</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">b</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">c</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
    <span class="kt">int</span> <span class="n">upperBound</span> <span class="o">=</span> <span class="no">SPECIES</span><span class="o">.</span><span class="na">loopBound</span><span class="o">(</span><span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">);</span>
    <span class="k">for</span> <span class="o">(;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">upperBound</span><span class="o">;</span> <span class="n">i</span> <span class="o">+=</span> <span class="no">SPECIES</span><span class="o">.</span><span class="na">length</span><span class="o">())</span> <span class="o">{</span>
        <span class="c1">// FloatVector va, vb, vc;</span>
        <span class="kt">var</span> <span class="n">va</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">fromArray</span><span class="o">(</span><span class="no">SPECIES</span><span class="o">,</span> <span class="n">a</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
        <span class="kt">var</span> <span class="n">vb</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">fromArray</span><span class="o">(</span><span class="no">SPECIES</span><span class="o">,</span> <span class="n">b</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
        <span class="kt">var</span> <span class="n">vc</span> <span class="o">=</span> <span class="n">va</span><span class="o">.</span><span class="na">mul</span><span class="o">(</span><span class="n">va</span><span class="o">)</span>
                   <span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">vb</span><span class="o">.</span><span class="na">mul</span><span class="o">(</span><span class="n">vb</span><span class="o">))</span>
                   <span class="o">.</span><span class="na">neg</span><span class="o">();</span>
        <span class="n">vc</span><span class="o">.</span><span class="na">intoArray</span><span class="o">(</span><span class="n">c</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">for</span> <span class="o">(;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="n">c</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">+</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">])</span> <span class="o">*</span> <span class="o">-</span><span class="mf">1.0f</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>From the perspective of the Java developer, this is just another way of expressing scalar computations. It might come across as being more verbose, but on the other hand it can bring spectacular performance gains.</p>

<h4 id="typical-use-cases-2">Typical Use Cases</h4>

<p>The Vector API provides a way to write complex vector algorithms in Java that perform extremely well, such as vectorized <code class="language-plaintext highlighter-rouge">hashCode</code> implementations or specialized array comparisons. Numerous domains can benefit from this, including machine learning, linear algebra, encryption, text processing, finance, and code within the JDK itself.</p>

<h4 id="whats-different-from-java-20-9">What’s Different From Java 20?</h4>

<p>Aside from a minor set of enhancements in the API, the biggest differences with Java 20 are:</p>

<ul>
  <li>Add the exclusive or (xor) operation to vector masks.</li>
  <li>Improve the performance of vector shuffles, especially when used to rearrange the elements of a vector and when converting between vectors.</li>
</ul>

<h4 id="more-information-9">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/448">JEP 448</a>.</p>

<h2 id="hotspot">HotSpot</h2>

<p>Java 21 introduces three changes to <a href="https://openjdk.org/groups/hotspot/">HotSpot</a>:</p>

<ul>
  <li>Generational ZGC;</li>
  <li>Deprecate the Windows 32-bit x86 Port for Removal;</li>
  <li>Prepare to Disallow the Dynamic Loading of Agents.</li>
</ul>

<blockquote>
  <p>The HotSpot JVM is the runtime engine that is developed by Oracle. It translates Java bytecode into machine code for the host operating system’s processor architecture.</p>
</blockquote>

<h3 id="jep-439-generational-zgc">JEP 439: Generational ZGC</h3>

<p>The Z Garbage Collector (ZGC) is a scalable, low-latency garbage collector. It has been <a href="https://openjdk.org/jeps/377">available for production use since Java 15</a> and has been designed to keep pause times consistent and short, even for very large heaps. It uses techniques like region-based memory management and compaction to achieve this.</p>

<p>Java 21 introduces an extension to ZGC that maintains separate <em>generations</em> for young and old objects, allowing ZGC to collect young objects (which tend to die young) more frequently. This will result in a significant performance gain for applications running with generational ZGC, without sacrificing any of the valuable properties that the Z garbage collector is already known for:</p>

<ul>
  <li>Pause times do not exceed 1 millisecond;</li>
  <li>Heap sizes from a few hundred megabytes up to many terabytes are supported;</li>
  <li>Minimal manual configuration is needed.</li>
</ul>

<p>The reason for handling young and old objects separately stems from the <a href="https://docs.oracle.com/en/java/javase/17/gctuning/garbage-collector-implementation.html#GUID-71D796B3-CBAB-4D80-B5C3-2620E45F6E5D">weak generational hypothesis</a>, stating that young objects tend to die young, while old objects tend to stick around. This means that collecting young objects requires fewer resources and yields more memory, while collecting old objects requires more resources and yields less memory. This is the reason we can improve the performance of applications that use ZGC by collecting young objects more frequently.</p>

<h4 id="whats-different-from-java-20-10">What’s Different From Java 20?</h4>

<p>The Z garbage collector in Java 20 was only able to behave in a non-generational way. Running it required the following command-line configuration:</p>

<p><code class="language-plaintext highlighter-rouge">$ java -XX:+UseZGC ...</code></p>

<p>To run your workload with the new Generational ZGC in Java 21, use the following configuration:</p>

<p><code class="language-plaintext highlighter-rouge">$ java -XX:+UseZGC -XX:+ZGenerational ...</code></p>

<p>As you can see, Generational ZGC has been introduced <em>alongside</em> non-generational ZGC. In a future release we can expect Generational ZGC to become the default configuration for the Z garbage collector, while an even later release will probably remove non-generational ZGC altogether.</p>

<h4 id="more-information-10">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/439">JEP 439</a>.</p>

<h3 id="jep-449-deprecate-the-windows-32-bit-x86-port-for-removal">JEP 449: Deprecate the Windows 32-bit x86 Port for Removal</h3>

<p>Supporting multiple platforms has been the focus of the Java ecosystem since the beginning. 
But older platforms cannot be supported indefinitely, and that is one of the reasons why the Windows 32-bit x86 port is now scheduled for removal.</p>

<p>There are a few reasons for this:</p>

<ul>
  <li>Windows 10, the last Windows operating system to support 32-bit operation, <a href="https://learn.microsoft.com/lifecycle/products/windows-10-home-and-pro">will reach end-of-life in October 2025</a>;</li>
  <li>The implementation of virtual threads on Windows 32-bit x86 is rudimentary to say the least: it uses a single platform thread for each virtual thread, effectively rendering the feature useless on this platform;</li>
  <li>It will allow the OpenJDK contributors to accelerate the development of new features and enhancements.</li>
</ul>

<h4 id="whats-different-from-java-20-11">What’s Different From Java 20?</h4>

<p>Configuring a Windows x86-32 build will now fail on JDK 21. 
This error can be suppressed by using the new build configuration option <code class="language-plaintext highlighter-rouge">--enable-deprecated-ports=yes</code>.
This means Windows x86-32 users can still use JDK 21; however a future release will actually remove the support, and by that time the affected users are expected to have migrated to Windows x64 and a 64-bit JVM.</p>

<h4 id="more-information-11">More Information</h4>

<p>For more information about this deprecation, see <a href="https://openjdk.org/jeps/449">JEP 449</a>.</p>

<h3 id="jep-451-prepare-to-disallow-the-dynamic-loading-of-agents">JEP 451: Prepare to Disallow the Dynamic Loading of Agents</h3>

<p>An <em>agent</em> is a component that can alter the code of a Java application while it is running. Introduced in JDK 5, agents provide a way for tools (such as profilers) to instrument classes, with the aim of altering the code in a class so that it emits events to be consumed by a tool outside the application. <em>Dynamically loaded agents</em> grant serviceability tools the capability to modify a <em>running</em> application. However, this capability is available to both tools and libraries, and it can just as easily be used for modifications with bad intentions. To assure integrity, stronger measures are needed to prevent the misuse by libraries of dynamically loaded agents. JEP 451 therefore proposes to require the dynamic loading of agents to be approved by the application owner. This means that in Java 21, the application owner will have to explicitly allow the dynamic loading of agents via a command-line option.</p>

<h4 id="whats-different-from-java-20-12">What’s Different From Java 20?</h4>

<p>Java 21 is the first version of Java that issues warnings when agents are loaded dynamically into a running JVM. A future release of the JDK will, by default, disallow the mechanism. Agents that are loaded at startup will still be allowed though, so serviceability tools that use that mechanism won’t be affected now or in the future. Maintainers of libraries which rely on dynamically agent loading will have to update their documentation to ask application owners for permission to load the agent at startup.</p>

<h4 id="more-information-12">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/451">JEP 451</a>.</p>

<h2 id="core--security-libs">Core &amp; Security Libs</h2>

<p>Java 21 also brings you two additions that are part of the Core Libs and Security Libs, respectively:</p>

<ul>
  <li>Sequenced Collections</li>
  <li>Key Encapsulation Mechanism API</li>
</ul>

<h3 id="jep-431-sequenced-collections">JEP 431: Sequenced Collections</h3>

<p>One of the most well-known APIs in Java is the <a href="https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/doc-files/coll-index.html">collections framework</a>, but did you know it doesn’t even contain a collection type that represents an ordered sequence of elements? Sure, there are some subtypes that support encounter order (such as <code class="language-plaintext highlighter-rouge">List</code>, <code class="language-plaintext highlighter-rouge">SortedSet</code> and <code class="language-plaintext highlighter-rouge">Deque</code>), but their common supertype is <code class="language-plaintext highlighter-rouge">Collection</code>, which does not support it. So support for encounter order is dispersed across the type hierarchy, and that leads to more challenges. Consider obtaining the first or last element of a collection, for instance. While numerous implementations accommodate this functionality, each adopts a distinct approach, and a few are not as obvious (or don’t support it at all). The process of sequentially traversing collection elements from the beginning to the end might appear simple and systematic, but iterating in reverse order is notably less straightforward.</p>

<p>It seems like the concept of a collection with defined encounter order exists in multiple places in the collections framework, but there is no single type that represents it. And this is the gap in the collections framework that will be filled by Sequenced Collections.</p>

<h4 id="new-interfaces">New Interfaces</h4>

<p>The JEP will introduce new interfaces for <em>sequenced collections</em>, <em>sequenced sets</em> and <em>sequenced maps</em>. They are retrofitted into the existing collections type hierarchy (making ample use of <a href="https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html">default methods</a>), as follows:</p>

<p><img src="/assets/images/blog/java-21-release-day/sequenced-collections-diagram.png" alt="A diagram of how the new interfaces related to sequence collections are retrofitted into the existing collections type hierarchy." /></p>
<blockquote>
  <p>Image from <a href="https://openjdk.org/jeps/431#Retrofitting">JEP 431</a></p>
</blockquote>

<p>A sequenced collection has first and last elements, allowing support for common operations at either end:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">interface</span> <span class="nc">SequencedCollection</span><span class="o">&lt;</span><span class="no">E</span><span class="o">&gt;</span> <span class="kd">extends</span> <span class="nc">Collection</span><span class="o">&lt;</span><span class="no">E</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="c1">// new method</span>
    <span class="nc">SequencedCollection</span><span class="o">&lt;</span><span class="no">E</span><span class="o">&gt;</span> <span class="nf">reversed</span><span class="o">();</span>
    <span class="c1">// methods promoted from Deque</span>
    <span class="kt">void</span> <span class="nf">addFirst</span><span class="o">(</span><span class="no">E</span><span class="o">);</span>
    <span class="kt">void</span> <span class="nf">addLast</span><span class="o">(</span><span class="no">E</span><span class="o">);</span>
    <span class="no">E</span> <span class="nf">getFirst</span><span class="o">();</span>
    <span class="no">E</span> <span class="nf">getLast</span><span class="o">();</span>
    <span class="no">E</span> <span class="nf">removeFirst</span><span class="o">();</span>
    <span class="no">E</span> <span class="nf">removeLast</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>

<p>A sequenced set is a <code class="language-plaintext highlighter-rouge">Set</code> that is a <code class="language-plaintext highlighter-rouge">SequencedCollection</code> that contains no duplicate elements:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">interface</span> <span class="nc">SequencedSet</span><span class="o">&lt;</span><span class="no">E</span><span class="o">&gt;</span> <span class="kd">extends</span> <span class="nc">Set</span><span class="o">&lt;</span><span class="no">E</span><span class="o">&gt;,</span> <span class="nc">SequencedCollection</span><span class="o">&lt;</span><span class="no">E</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="nc">SequencedSet</span><span class="o">&lt;</span><span class="no">E</span><span class="o">&gt;</span> <span class="nf">reversed</span><span class="o">();</span>    <span class="c1">// covariant override</span>
<span class="o">}</span>
</code></pre></div></div>

<p>A sequenced map is a <code class="language-plaintext highlighter-rouge">Map</code> whose entries have a defined encounter order:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">interface</span> <span class="nc">SequencedMap</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span><span class="no">V</span><span class="o">&gt;</span> <span class="kd">extends</span> <span class="nc">Map</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span><span class="no">V</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="c1">// new methods</span>
    <span class="nc">SequencedMap</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span><span class="no">V</span><span class="o">&gt;</span> <span class="nf">reversed</span><span class="o">();</span>
    <span class="nc">SequencedSet</span><span class="o">&lt;</span><span class="no">K</span><span class="o">&gt;</span> <span class="nf">sequencedKeySet</span><span class="o">();</span>
    <span class="nc">SequencedCollection</span><span class="o">&lt;</span><span class="no">V</span><span class="o">&gt;</span> <span class="nf">sequencedValues</span><span class="o">();</span>
    <span class="nc">SequencedSet</span><span class="o">&lt;</span><span class="nc">Entry</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span><span class="no">V</span><span class="o">&gt;&gt;</span> <span class="nf">sequencedEntrySet</span><span class="o">();</span>
    <span class="no">V</span> <span class="nf">putFirst</span><span class="o">(</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">);</span>
    <span class="no">V</span> <span class="nf">putLast</span><span class="o">(</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">);</span>
    <span class="c1">// methods promoted from NavigableMap</span>
    <span class="nc">Entry</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="nf">firstEntry</span><span class="o">();</span>
    <span class="nc">Entry</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="nf">lastEntry</span><span class="o">();</span>
    <span class="nc">Entry</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="nf">pollFirstEntry</span><span class="o">();</span>
    <span class="nc">Entry</span><span class="o">&lt;</span><span class="no">K</span><span class="o">,</span> <span class="no">V</span><span class="o">&gt;</span> <span class="nf">pollLastEntry</span><span class="o">();</span>
<span class="o">}</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">Collections</code> utility class has also been extended to create unmodifiable wrappers for the three new types:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Collections.unmodifiableSequencedCollection(sequencedCollection)</code></li>
  <li><code class="language-plaintext highlighter-rouge">Collections.unmodifiableSequencedSet(sequencedSet)</code></li>
  <li><code class="language-plaintext highlighter-rouge">Collections.unmodifiableSequencedMap(sequencedMap)</code></li>
</ul>

<h4 id="whats-different-from-java-20-13">What’s Different From Java 20?</h4>

<p>Java 20 didn’t contain anything related to sequenced collections yet, so everything that you read about it so far is as new as it gets! However, the feature that now has been delivered is the result of an incremental evolution of an earlier proposal called <a href="http://mail.openjdk.org/pipermail/core-libs-dev/2021-April/076461.html">reversible collections</a>. And if you’re up for a trip down memory lane: the earliest form of this proposal was the one by Tagir Valeev’s from 2020 called <a href="http://mail.openjdk.org/pipermail/core-libs-dev/2020-April/066028.html">OrderedMap/OrderedSet</a>. These proposals have played a big part in shaping the feature that is now called ‘sequenced collections’ and that we get to enjoy in Java 21.</p>

<h4 id="more-information-13">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/431">JEP 431</a>.</p>

<h3 id="jep-452-key-encapsulation-mechanism-api">JEP 452: Key Encapsulation Mechanism API</h3>

<p>A protocol like Transport Layer Security (TLS) relies heavily on public key encryption schemes in order to provide a secure way for a sender and recipient to share information.
But public key encryption schemes are usually less efficient than symmetric encryption schemes, which instead focus on establishing a shared symmetric key as the basis of all future communication between sender and recipient. Such a key is typically produced by a <em>key encapsulation mechanism</em> (or KEM), and JEP 452 proposes to introduce an API for it.</p>

<h4 id="components">Components</h4>

<p>A KEM needs the following components:</p>

<ul>
  <li>a key pair generation function that returns a key pair containing a public key and a private key.</li>
</ul>

<blockquote>
  <p>This function is already covered by the existing <a href="https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/security/KeyPairGenerator.html"><code class="language-plaintext highlighter-rouge">KeyPairGenerator</code> API</a>.</p>
</blockquote>

<ul>
  <li>a key encapsulation function, called by the sender, that takes the receiver’s public key and an encryption option; it returns a secret key and a <em>ciphertext</em>. The sender sends the key encapsulation message to the receiver.</li>
</ul>

<blockquote>
  <p>The new <code class="language-plaintext highlighter-rouge">KEM</code> class contains an encapsulation function.</p>
</blockquote>

<ul>
  <li>a key decapsulation function, called by the receiver, that takes the receiver’s private key and the received key encapsulation message; it returns the secret key.</li>
</ul>

<blockquote>
  <p>The new <code class="language-plaintext highlighter-rouge">KEM</code> class contains a decapsulation function.</p>
</blockquote>

<h4 id="kem-class"><code class="language-plaintext highlighter-rouge">KEM</code> class</h4>

<p>For illustration purposes, the <code class="language-plaintext highlighter-rouge">KEM</code> class that is mentioned in the JEP is listed below:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">javax.crypto</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">DecapsulateException</span> <span class="kd">extends</span> <span class="nc">GeneralSecurityException</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">KEM</span> <span class="o">{</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="no">KEM</span> <span class="nf">getInstance</span><span class="o">(</span><span class="nc">String</span> <span class="n">alg</span><span class="o">)</span>
        <span class="kd">throws</span> <span class="nc">NoSuchAlgorithmException</span><span class="o">;</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="no">KEM</span> <span class="nf">getInstance</span><span class="o">(</span><span class="nc">String</span> <span class="n">alg</span><span class="o">,</span> <span class="nc">Provider</span> <span class="n">p</span><span class="o">)</span>
        <span class="kd">throws</span> <span class="nc">NoSuchAlgorithmException</span><span class="o">;</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="no">KEM</span> <span class="nf">getInstance</span><span class="o">(</span><span class="nc">String</span> <span class="n">alg</span><span class="o">,</span> <span class="nc">String</span> <span class="n">p</span><span class="o">)</span>
        <span class="kd">throws</span> <span class="nc">NoSuchAlgorithmException</span><span class="o">,</span> <span class="nc">NoSuchProviderException</span><span class="o">;</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Encapsulated</span> <span class="o">{</span>
        <span class="kd">public</span> <span class="nf">Encapsulated</span><span class="o">(</span><span class="nc">SecretKey</span> <span class="n">key</span><span class="o">,</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">encapsulation</span><span class="o">,</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">params</span><span class="o">);</span>
        <span class="kd">public</span> <span class="nc">SecretKey</span> <span class="nf">key</span><span class="o">();</span>
        <span class="kd">public</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">encapsulation</span><span class="o">();</span>
        <span class="kd">public</span> <span class="kt">byte</span><span class="o">[]</span> <span class="nf">params</span><span class="o">();</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Encapsulator</span> <span class="o">{</span>
        <span class="nc">String</span> <span class="nf">providerName</span><span class="o">();</span>
        <span class="kt">int</span> <span class="nf">secretSize</span><span class="o">();</span>           <span class="c1">// Size of the shared secret</span>
        <span class="kt">int</span> <span class="nf">encapsulationSize</span><span class="o">();</span>    <span class="c1">// Size of the key encapsulation message</span>
        <span class="nc">Encapsulated</span> <span class="nf">encapsulate</span><span class="o">();</span>
        <span class="nc">Encapsulated</span> <span class="nf">encapsulate</span><span class="o">(</span><span class="kt">int</span> <span class="n">from</span><span class="o">,</span> <span class="kt">int</span> <span class="n">to</span><span class="o">,</span> <span class="nc">String</span> <span class="n">algorithm</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nc">Encapsulator</span> <span class="nf">newEncapsulator</span><span class="o">(</span><span class="nc">PublicKey</span> <span class="n">pk</span><span class="o">)</span>
            <span class="kd">throws</span> <span class="nc">InvalidKeyException</span><span class="o">;</span>
    <span class="kd">public</span> <span class="nc">Encapsulator</span> <span class="nf">newEncapsulator</span><span class="o">(</span><span class="nc">PublicKey</span> <span class="n">pk</span><span class="o">,</span> <span class="nc">SecureRandom</span> <span class="n">sr</span><span class="o">)</span>
            <span class="kd">throws</span> <span class="nc">InvalidKeyException</span><span class="o">;</span>
    <span class="kd">public</span> <span class="nc">Encapsulator</span> <span class="nf">newEncapsulator</span><span class="o">(</span><span class="nc">PublicKey</span> <span class="n">pk</span><span class="o">,</span> <span class="nc">AlgorithmParameterSpec</span> <span class="n">spec</span><span class="o">,</span>
                                        <span class="nc">SecureRandom</span> <span class="n">sr</span><span class="o">)</span>
            <span class="kd">throws</span> <span class="nc">InvalidAlgorithmParameterException</span><span class="o">,</span> <span class="nc">InvalidKeyException</span><span class="o">;</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Decapsulator</span> <span class="o">{</span>
        <span class="nc">String</span> <span class="nf">providerName</span><span class="o">();</span>
        <span class="kt">int</span> <span class="nf">secretSize</span><span class="o">();</span>           <span class="c1">// Size of the shared secret</span>
        <span class="kt">int</span> <span class="nf">encapsulationSize</span><span class="o">();</span>    <span class="c1">// Size of the key encapsulation message</span>
        <span class="nc">SecretKey</span> <span class="nf">decapsulate</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">encapsulation</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">DecapsulateException</span><span class="o">;</span>
        <span class="nc">SecretKey</span> <span class="nf">decapsulate</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">encapsulation</span><span class="o">,</span> <span class="kt">int</span> <span class="n">from</span><span class="o">,</span> <span class="kt">int</span> <span class="n">to</span><span class="o">,</span>
                              <span class="nc">String</span> <span class="n">algorithm</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">DecapsulateException</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="nc">Decapsulator</span> <span class="nf">newDecapsulator</span><span class="o">(</span><span class="nc">PrivateKey</span> <span class="n">sk</span><span class="o">)</span>
            <span class="kd">throws</span> <span class="nc">InvalidKeyException</span><span class="o">;</span>
    <span class="kd">public</span> <span class="nc">Decapsulator</span> <span class="nf">newDecapsulator</span><span class="o">(</span><span class="nc">PrivateKey</span> <span class="n">sk</span><span class="o">,</span> <span class="nc">AlgorithmParameterSpec</span> <span class="n">spec</span><span class="o">)</span>
            <span class="kd">throws</span> <span class="nc">InvalidAlgorithmParameterException</span><span class="o">,</span> <span class="nc">InvalidKeyException</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<blockquote>
  <p>The <code class="language-plaintext highlighter-rouge">getInstance</code> methods create a new <code class="language-plaintext highlighter-rouge">KEM</code> object that implements the specified algorithm.</p>
</blockquote>

<p>And here is an example of how to use this class (again, taken from the JEP):</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Receiver side</span>
<span class="nc">KeyPairGenerator</span> <span class="n">g</span> <span class="o">=</span> <span class="nc">KeyPairGenerator</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ABC"</span><span class="o">);</span>
<span class="nc">KeyPair</span> <span class="n">kp</span> <span class="o">=</span> <span class="n">g</span><span class="o">.</span><span class="na">generateKeyPair</span><span class="o">();</span>
<span class="n">publishKey</span><span class="o">(</span><span class="n">kp</span><span class="o">.</span><span class="na">getPublic</span><span class="o">());</span>

<span class="c1">// Sender side</span>
<span class="no">KEM</span> <span class="n">kemS</span> <span class="o">=</span> <span class="no">KEM</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ABC-KEM"</span><span class="o">);</span>
<span class="nc">PublicKey</span> <span class="n">pkR</span> <span class="o">=</span> <span class="n">retrieveKey</span><span class="o">();</span>
<span class="nc">ABCKEMParameterSpec</span> <span class="n">specS</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ABCKEMParameterSpec</span><span class="o">(...);</span>
<span class="no">KEM</span><span class="o">.</span><span class="na">Encapsulator</span> <span class="n">e</span> <span class="o">=</span> <span class="n">kemS</span><span class="o">.</span><span class="na">newEncapsulator</span><span class="o">(</span><span class="n">pkR</span><span class="o">,</span> <span class="n">specS</span><span class="o">,</span> <span class="kc">null</span><span class="o">);</span>
<span class="no">KEM</span><span class="o">.</span><span class="na">Encapsulated</span> <span class="n">enc</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="na">encapsulate</span><span class="o">();</span>
<span class="nc">SecretKey</span> <span class="n">secS</span> <span class="o">=</span> <span class="n">enc</span><span class="o">.</span><span class="na">key</span><span class="o">();</span>
<span class="n">sendBytes</span><span class="o">(</span><span class="n">enc</span><span class="o">.</span><span class="na">encapsulation</span><span class="o">());</span>
<span class="n">sendBytes</span><span class="o">(</span><span class="n">enc</span><span class="o">.</span><span class="na">params</span><span class="o">());</span>

<span class="c1">// Receiver side</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">em</span> <span class="o">=</span> <span class="n">receiveBytes</span><span class="o">();</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">params</span> <span class="o">=</span> <span class="n">receiveBytes</span><span class="o">();</span>
<span class="no">KEM</span> <span class="n">kemR</span> <span class="o">=</span> <span class="no">KEM</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ABC-KEM"</span><span class="o">);</span>
<span class="nc">AlgorithmParameters</span> <span class="n">algParams</span> <span class="o">=</span> <span class="nc">AlgorithmParameters</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="s">"ABC-KEM"</span><span class="o">);</span>
<span class="n">algParams</span><span class="o">.</span><span class="na">init</span><span class="o">(</span><span class="n">params</span><span class="o">);</span>
<span class="nc">ABCKEMParameterSpec</span> <span class="n">specR</span> <span class="o">=</span> <span class="n">algParams</span><span class="o">.</span><span class="na">getParameterSpec</span><span class="o">(</span><span class="nc">ABCKEMParameterSpec</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
<span class="no">KEM</span><span class="o">.</span><span class="na">Decapsulator</span> <span class="n">d</span> <span class="o">=</span> <span class="n">kemR</span><span class="o">.</span><span class="na">newDecapsulator</span><span class="o">(</span><span class="n">kp</span><span class="o">.</span><span class="na">getPrivate</span><span class="o">(),</span> <span class="n">specR</span><span class="o">);</span>
<span class="nc">SecretKey</span> <span class="n">secR</span> <span class="o">=</span> <span class="n">d</span><span class="o">.</span><span class="na">decapsulate</span><span class="o">(</span><span class="n">em</span><span class="o">);</span>

<span class="c1">// secS and secR will be identical</span>
</code></pre></div></div>

<h4 id="whats-different-from-java-20-14">What’s Different From Java 20?</h4>

<p>The Key Encapsulation Mechanism API didn’t exist yet in Java 20; it was newly added in Java 21.</p>

<h4 id="more-information-14">More Information</h4>

<p>There is a bit more to this API than we were able to cover here (like different <em>KEM configurations</em>, for example), so to get the full picture you could have a look at <a href="https://openjdk.org/jeps/452">JEP 452</a>.</p>

<h2 id="final-thoughts">Final thoughts</h2>

<p>Phew! I guess it’s safe to say that JDK 21 turned out to be quite the update, with no less than 15 JEPs delivered! And that’s not even all that’s new: thousands of other updates were included in this new release, including various performance and stability updates. Our favourite language is clearly more alive than ever, and I think it’s due to Java’s continuing focus on its best traits: performance, stability, security, compatibility and maintainability. Wishing you many happy hours of developing with Java 21!</p>]]></content><author><name>Hanno Embregts</name></author><category term="java" /><summary type="html"><![CDATA[Java 21 is available today, and it's quite the update. It brings us 15 (!) JEPS, finalizing features like Record Patterns & Virtual Threads and previewing new ones like String Templates. This blog post has all the info!]]></summary></entry><entry><title type="html">Configuring IntelliJ IDEA To Try Out Java’s Preview Features</title><link href="https://hanno.codes/2023/07/16/configuring-intellij-idea-to-try-out-javas-preview-features/" rel="alternate" type="text/html" title="Configuring IntelliJ IDEA To Try Out Java’s Preview Features" /><published>2023-07-16T19:30:00+00:00</published><updated>2023-07-16T19:30:00+00:00</updated><id>https://hanno.codes/2023/07/16/configuring-intellij-idea-to-try-out-javas-preview-features</id><content type="html" xml:base="https://hanno.codes/2023/07/16/configuring-intellij-idea-to-try-out-javas-preview-features/"><![CDATA[<p>Currently I’m working on both an <a href="/articles/">article</a> and a <a href="/talks/#javas-concurrency-journey-continues">talk</a> on structured concurrency in Java.
Most of the work I did until now was based on <a href="https://openjdk.org/jeps/437">JEP 437</a>, which has been in Second Incubator status in Java 20.
Structured concurrency is now set to appear in Preview Status as part of Java 21 (see <a href="https://openjdk.org/jeps/453">JEP 453</a>), and I was eager to try out the feature and see what had changed since Java 20.
It surprised me how much configuration I needed to do to get IntelliJ IDEA to play nice with this preview feature.
Here’s an overview of what I did to get it working.</p>

<p><img src="/assets/images/blog/configuring-intellij-idea-for-trying-out-javas-preview-features/settings.jpg" alt="Settings" /></p>
<blockquote>
  <p>Image by Pixabay from <a href="https://www.pexels.com/photo/settings-android-tab-270700/">Pexels</a></p>
</blockquote>

<h2 id="downloading-an-early-access-build-of-jdk-21">Downloading an Early-Access Build of JDK 21</h2>

<p>I started out by downloading an early-access build of JDK 21.
Using <a href="https://sdkman.io/">SDKMAN!</a>, this only takes like a minute or so.
Running <code class="language-plaintext highlighter-rouge">sdk list java</code> lists all JDK binaries that are currently available.
This time, I opted for the latest early-access build of OpenJDK 21, so I ran:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sdk <span class="nb">install </span>java 21.ea.31-open
</code></pre></div></div>

<p>…and all was well.</p>

<h2 id="updating-the-ide">Updating the IDE</h2>

<p>Then, I updated IntelliJ IDEA to the latest version (which is <code class="language-plaintext highlighter-rouge">2023.1.4</code> at the time of writing).
This is a rather crucial step, because older versions usually don’t have support for the latest Java features.</p>

<h2 id="setting-the-sdk-and-language-level">Setting the SDK and Language Level</h2>

<p>Then, I opened the Module Settings (<code class="language-plaintext highlighter-rouge">⌘+↓</code> or <code class="language-plaintext highlighter-rouge">Ctrl+Alt+Shift+S</code> if you prefer shortcuts) and changed the SDK to OpenJDK 21 (the one I just downloaded). 
And I set the ‘Language level’ to ‘X - Experimental features’.
Note that the ‘Modules’ tab has a separate setting for ‘Language level’, so I set that to ‘X - Experimental features’ as well.</p>

<p><img src="/assets/images/blog/configuring-intellij-idea-for-trying-out-javas-preview-features/x-experimental-features.png" alt="Configuring Module Settings" /></p>

<h2 id="first-try">First Try</h2>

<p>After that I wrote some <a href="https://github.com/hannotify/structured-concurrency-bar">concurrent code</a> that used a <code class="language-plaintext highlighter-rouge">StructuredTaskScope</code>, created a <code class="language-plaintext highlighter-rouge">Main</code> class and ran its <code class="language-plaintext highlighter-rouge">main()</code> method just to give it a try.
Then this happened:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>java: java.util.concurrent.StructuredTaskScope is a preview API and is disabled by default.
  (use --enable-preview to enable preview APIs)
</code></pre></div></div>

<p>Which made sense of course, as I hadn’t allowed the use of preview features yet in any of the configuration.</p>

<h2 id="enabling-preview-features-in-the-run-configuration">Enabling Preview Features in the Run Configuration</h2>

<p>So I opened the run configuration that belonged to the <code class="language-plaintext highlighter-rouge">Main</code> class to add the <code class="language-plaintext highlighter-rouge">--enable-preview</code> flag to the VM options.
In recent versions of IntelliJ IDEA the ‘Add VM options’ functionality has been hidden underneath the ‘Modify options’ dropdown.</p>

<p><img src="/assets/images/blog/configuring-intellij-idea-for-trying-out-javas-preview-features/add-vm-options.png" alt="Add VM options" /></p>

<p>Upon activating ‘Add VM options’ a ‘VM options’ text field appeared, in which I entered <code class="language-plaintext highlighter-rouge">--enable-preview</code>.</p>

<h2 id="second-try">Second Try</h2>

<p>After applying the run config changes, I ran the <code class="language-plaintext highlighter-rouge">Main</code> class again.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>java: java.util.concurrent.StructuredTaskScope is a preview API and is disabled by default.
  (use --enable-preview to enable preview APIs)
</code></pre></div></div>

<p>Umm, say what?
That didn’t make sense to me. 
I took some time to research the issue, and according to this <a href="https://stackoverflow.com/questions/72083752/enable-preview-features-in-an-early-access-version-of-java-in-intellij">StackOverflow post</a>, I had forgotten to enable the preview features on a per-module basis.</p>

<h2 id="enabling-preview-features-per-module">Enabling Preview Features Per-Module</h2>

<p>In order to do so, I popped open ‘Settings’ (<code class="language-plaintext highlighter-rouge">⌘+,</code> or <code class="language-plaintext highlighter-rouge">Ctrl+Alt+S</code> if you prefer shortcuts), went to ‘Build, Execution, Deployment’ &gt; ‘Compiler’ &gt; ‘Java Compiler’ and added <code class="language-plaintext highlighter-rouge">--enable-preview</code> in the little table that’s directly beneath ‘Override compiler parameters per-module’.</p>

<blockquote>
  <p>You can edit the cells in this table by double-clicking.</p>
</blockquote>

<p><img src="/assets/images/blog/configuring-intellij-idea-for-trying-out-javas-preview-features/per-module-settings.png" alt="Override compiler parameters per-module" /></p>

<h2 id="final-try">Final Try</h2>

<p>And that’s when things started working!
When I ran the <code class="language-plaintext highlighter-rouge">Main</code> class again, I finally got the output I was expecting.
Why this configuration is (seemingly) so complicated is beyond me.
If you happen to know more about it, feel free to let me know!
And until that happens: have fun playing around with Java’s preview features in IntelliJ IDEA!</p>]]></content><author><name>Hanno Embregts</name></author><category term="java" /><category term="intellij-idea" /><summary type="html"><![CDATA[This is how I configured my IntelliJ IDEA to be able to try out Java's preview features.]]></summary></entry><entry><title type="html">It’s Java 20 Release Day! Here’s What’s New</title><link href="https://hanno.codes/2023/03/21/java-20-release-day-heres-whats-new/" rel="alternate" type="text/html" title="It’s Java 20 Release Day! Here’s What’s New" /><published>2023-03-21T02:30:00+00:00</published><updated>2023-03-21T02:30:00+00:00</updated><id>https://hanno.codes/2023/03/21/java-20-release-day-heres-whats-new</id><content type="html" xml:base="https://hanno.codes/2023/03/21/java-20-release-day-heres-whats-new/"><![CDATA[<p>This will be a good day, because it’s Java 20 release day! It’s been six months since Java 19 was released, and so it’s time for another fresh wave of Java features. This post will take you on a tour through all JEPs that come with this release and give you a brief introduction of each one of them. Where applicable the differences with Java 19 are highlighted and a few typical use cases are provided, so that you’ll be more than ready to use these features after you’ve finished reading!</p>

<p><img src="/assets/images/blog/package-just-for-you.jpg" alt="Package, just for you" /></p>
<blockquote>
  <p>Image from <a href="https://pxhere.com/nl/photo/535806">PxHere</a></p>
</blockquote>

<h2 id="from-project-amber">From Project Amber</h2>

<p>Java 20 contains two features that originated from <a href="https://openjdk.org/projects/amber/">Project Amber</a>:</p>

<ul>
  <li>Pattern Matching for switch;</li>
  <li>Record Patterns.</li>
</ul>

<blockquote>
  <p>The goal of Project Amber is to explore and incubate smaller, productivity-oriented Java language features.</p>
</blockquote>

<h3 id="jep-433-pattern-matching-for-switch-fourth-preview">JEP 433: Pattern Matching for switch (Fourth Preview)</h3>

<p>The feature ‘Pattern Matching for switch’ that was first introduced in Java 17 has reached its fourth preview stage, now that Java 20 has been released. The feature has always gathered a lot of feedback in the past, and on top of that it needs alignment with the related Record Patterns preview feature. In the end there are plenty of reasons to keep it in preview just a little longer.</p>

<p>Since Java 16 we are able to avoid casting after <code class="language-plaintext highlighter-rouge">instanceof</code> checks by using ‘Pattern Matching for instanceof’. Let’s see how that works in a code example.</p>

<blockquote>
  <p>Code examples that illustrate this JEP were taken from my conference talk <a href="https://hanno.codes/talks/#pattern-matching-small-enhancement-or-major-feature">“Pattern Matching: Small Enhancement or Major Feature?”</a>.</p>
</blockquote>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="nc">String</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
    <span class="nc">String</span> <span class="n">formatted</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
    <span class="k">if</span> <span class="o">(</span><span class="n">effect</span> <span class="k">instanceof</span> <span class="nc">Delay</span> <span class="n">de</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">formatted</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Delay active of %d ms."</span><span class="o">,</span> <span class="n">de</span><span class="o">.</span><span class="na">timeInMs</span><span class="o">());</span>
    <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">effect</span> <span class="k">instanceof</span> <span class="nc">Reverb</span> <span class="n">re</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">formatted</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Reverb active of type %s and roomSize %d."</span><span class="o">,</span> <span class="n">re</span><span class="o">.</span><span class="na">name</span><span class="o">(),</span> <span class="n">re</span><span class="o">.</span><span class="na">roomSize</span><span class="o">());</span>
    <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">effect</span> <span class="k">instanceof</span> <span class="nc">Overdrive</span> <span class="n">ov</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">formatted</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Overdrive active with gain %d."</span><span class="o">,</span> <span class="n">ov</span><span class="o">.</span><span class="na">gain</span><span class="o">());</span>
    <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">effect</span> <span class="k">instanceof</span> <span class="nc">Tremolo</span> <span class="n">tr</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">formatted</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tremolo active with depth %d and rate %d."</span><span class="o">,</span> <span class="n">tr</span><span class="o">.</span><span class="na">depth</span><span class="o">(),</span> <span class="n">tr</span><span class="o">.</span><span class="na">rate</span><span class="o">());</span>
    <span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">effect</span> <span class="k">instanceof</span> <span class="nc">Tuner</span> <span class="n">tu</span><span class="o">)</span> <span class="o">{</span>
        <span class="n">formatted</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tuner active with pitch %d. Muting all signal!"</span><span class="o">,</span> <span class="n">tu</span><span class="o">.</span><span class="na">pitchInHz</span><span class="o">());</span>
    <span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
        <span class="n">formatted</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Unknown effect active: %s."</span><span class="o">,</span> <span class="n">effect</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="n">formatted</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>

<p>This code is still riddled with ceremony, though. On top of that it leaves room for subtle bugs — what if you added an else-if branch that didn’t assign anything to <code class="language-plaintext highlighter-rouge">formatted</code>? So in the spirit of this JEP (and its predecessors), let’s see what pattern matching in a switch statement (or even better: in a switch <em>expression</em>) would look like:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="nc">String</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="nf">switch</span><span class="o">(</span><span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">case</span> <span class="nc">Delay</span> <span class="n">de</span>      <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Delay active of %d ms."</span><span class="o">,</span> <span class="n">de</span><span class="o">.</span><span class="na">timeInMs</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Reverb</span> <span class="n">re</span>     <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Reverb active of type %s and roomSize %d."</span><span class="o">,</span> <span class="n">re</span><span class="o">.</span><span class="na">name</span><span class="o">(),</span> <span class="n">re</span><span class="o">.</span><span class="na">roomSize</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Overdrive</span> <span class="n">ov</span>  <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Overdrive active with gain %d."</span><span class="o">,</span> <span class="n">ov</span><span class="o">.</span><span class="na">gain</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Tremolo</span> <span class="n">tr</span>    <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tremolo active with depth %d and rate %d."</span><span class="o">,</span> <span class="n">tr</span><span class="o">.</span><span class="na">depth</span><span class="o">(),</span> <span class="n">tr</span><span class="o">.</span><span class="na">rate</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Tuner</span> <span class="n">tu</span>      <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tuner active with pitch %d. Muting all signal!"</span><span class="o">,</span> <span class="n">tu</span><span class="o">.</span><span class="na">pitchInHz</span><span class="o">());</span>
        <span class="k">case</span> <span class="kc">null</span><span class="o">,</span> <span class="k">default</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Unknown or empty effect active: %s."</span><span class="o">,</span> <span class="n">effect</span><span class="o">);</span>
    <span class="o">};</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Pattern matching for switch made our code far more elegant here. We’re even able to address possible <code class="language-plaintext highlighter-rouge">null</code>s by defining a specific case for them or combining it with the default case (which is what we’ve done here).</p>

<p>Checking an additional condition on top of the pattern match is easily done with a <em>guard</em> (the part after the <code class="language-plaintext highlighter-rouge">when</code> keyword in the code below):</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="nc">String</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">,</span> <span class="nc">Guitar</span> <span class="n">guitar</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="nf">switch</span><span class="o">(</span><span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">case</span> <span class="nc">Delay</span> <span class="n">de</span>      <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Delay active of %d ms."</span><span class="o">,</span> <span class="n">de</span><span class="o">.</span><span class="na">timeInMs</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Reverb</span> <span class="n">re</span>     <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Reverb active of type %s and roomSize %d."</span><span class="o">,</span> <span class="n">re</span><span class="o">.</span><span class="na">name</span><span class="o">(),</span> <span class="n">re</span><span class="o">.</span><span class="na">roomSize</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Overdrive</span> <span class="n">ov</span>  <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Overdrive active with gain %d."</span><span class="o">,</span> <span class="n">ov</span><span class="o">.</span><span class="na">gain</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Tremolo</span> <span class="n">tr</span>    <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tremolo active with depth %d and rate %d."</span><span class="o">,</span> <span class="n">tr</span><span class="o">.</span><span class="na">depth</span><span class="o">(),</span> <span class="n">tr</span><span class="o">.</span><span class="na">rate</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Tuner</span> <span class="n">tu</span> <span class="n">when</span> <span class="o">!</span><span class="n">guitar</span><span class="o">.</span><span class="na">isInTune</span><span class="o">()</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tuner active with pitch %d. Muting all signal!"</span><span class="o">,</span> <span class="n">tu</span><span class="o">.</span><span class="na">pitchInHz</span><span class="o">());</span>
        <span class="k">case</span> <span class="nc">Tuner</span> <span class="n">tu</span>      <span class="o">-&gt;</span> <span class="s">"Guitar is already in tune."</span><span class="o">;</span>
        <span class="k">case</span> <span class="kc">null</span><span class="o">,</span> <span class="k">default</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Unknown or empty effect active: %s."</span><span class="o">,</span> <span class="n">effect</span><span class="o">);</span>
    <span class="o">};</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here, the guard makes sure that intricate boolean logic can still be expressed in a concise way. Having to nest <code class="language-plaintext highlighter-rouge">if</code> statements to test this logic within a case branch would not only be more verbose, but also potentially introduce subtle bugs that we set out to avoid in the first place.</p>

<h4 id="whats-different-from-java-19">What’s Different From Java 19?</h4>

<p>A few changes were made to this feature compared to Java 19:</p>

<ul>
  <li>When a pattern match fails abruptly, a <code class="language-plaintext highlighter-rouge">MatchException</code> is now thrown.</li>
  <li>Inference of type arguments for <a href="#jep-432-record-patterns-second-preview">record patterns</a> is now supported in switch expressions and statements. This means that you can now use <code class="language-plaintext highlighter-rouge">var</code> in the patterns you want to match.</li>
</ul>

<h4 id="more-information">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/433">JEP 433</a>.</p>

<h3 id="jep-432-record-patterns-second-preview">JEP 432: Record Patterns (Second Preview)</h3>

<p>Pattern matching is a feature in Java that is being rolled out gradually over multiple Java versions. Being able to deconstruct an object using patterns was always one of the ultimate goals of the feature arc. With the introduction of <em>record patterns</em>, deconstructing records is now possible, along with nesting record and type patterns to enable a powerful, declarative, and composable form of data navigation and processing.</p>

<p><a href="https://openjdk.org/jeps/395">Records</a> are transparent carriers for data. Code that receives an instance of a record will typically extract the data, known as the components. This was also the case in our ‘Pattern Matching for switch’ code example, if we assume that all implementations of the <code class="language-plaintext highlighter-rouge">Effect</code> interface were in fact records there. In that piece of code it is clear that the pattern variables only serve to access the record fields. Using record patterns we can avoid having to create pattern variables altogether:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">static</span> <span class="nc">String</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="nf">switch</span><span class="o">(</span><span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">case</span> <span class="nf">Delay</span><span class="o">(</span><span class="kt">int</span> <span class="n">timeInMs</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Delay active of %d ms."</span><span class="o">,</span> <span class="n">timeInMs</span><span class="o">);</span>
        <span class="k">case</span> <span class="nf">Reverb</span><span class="o">(</span><span class="nc">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">int</span> <span class="n">roomSize</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Reverb active of type %s and roomSize %d."</span><span class="o">,</span> <span class="n">name</span><span class="o">,</span> <span class="n">roomSize</span><span class="o">);</span>
        <span class="k">case</span> <span class="nf">Overdrive</span><span class="o">(</span><span class="kt">int</span> <span class="n">gain</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Overdrive active with gain %d."</span><span class="o">,</span> <span class="n">gain</span><span class="o">);</span>
        <span class="k">case</span> <span class="nf">Tremolo</span><span class="o">(</span><span class="kt">int</span> <span class="n">depth</span><span class="o">,</span> <span class="kt">int</span> <span class="n">rate</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tremolo active with depth %d and rate %d."</span><span class="o">,</span> <span class="n">depth</span><span class="o">,</span> <span class="n">rate</span><span class="o">);</span>
        <span class="k">case</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">int</span> <span class="n">pitchInHz</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tuner active with pitch %d. Muting all signal!"</span><span class="o">,</span> <span class="n">pitchInHz</span><span class="o">);</span>
        <span class="k">case</span> <span class="kc">null</span><span class="o">,</span> <span class="k">default</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Unknown or empty effect active: %s."</span><span class="o">,</span> <span class="n">effect</span><span class="o">);</span>
    <span class="o">};</span>
<span class="o">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Delay(int timeInMs)</code> is a record pattern here, deconstructing the <code class="language-plaintext highlighter-rouge">Delay</code> instance into its components. And this mechanism can become even more powerful when we apply it to a more complicated object graph by using <em>nested</em> record patterns:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">record</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">int</span> <span class="n">pitchInHz</span><span class="o">,</span> <span class="nc">Note</span> <span class="n">note</span><span class="o">)</span> <span class="kd">implements</span> <span class="nc">Effect</span> <span class="o">{}</span>
<span class="n">record</span> <span class="nf">Note</span><span class="o">(</span><span class="nc">String</span> <span class="n">note</span><span class="o">)</span> <span class="o">{}</span>

<span class="kd">class</span> <span class="nc">TunerApplier</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="nc">String</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">,</span> <span class="nc">Guitar</span> <span class="n">guitar</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="nf">switch</span><span class="o">(</span><span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">case</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">int</span> <span class="n">pitch</span><span class="o">,</span> <span class="nc">Note</span><span class="o">(</span><span class="nc">String</span> <span class="n">note</span><span class="o">))</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tuner active with pitch %d on note %s"</span><span class="o">,</span> <span class="n">pitch</span><span class="o">,</span> <span class="n">note</span><span class="o">);</span>
        <span class="o">};</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<h4 id="inference-of-type-arguments">Inference of type arguments</h4>

<p>Nested record patterns also benefit from <em>inference of type arguments</em>. For example:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">TunerApplier</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="nc">String</span> <span class="nf">apply</span><span class="o">(</span><span class="nc">Effect</span> <span class="n">effect</span><span class="o">,</span> <span class="nc">Guitar</span> <span class="n">guitar</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="nf">switch</span><span class="o">(</span><span class="n">effect</span><span class="o">)</span> <span class="o">{</span>
            <span class="k">case</span> <span class="nf">Tuner</span><span class="o">(</span><span class="kt">var</span> <span class="n">pitch</span><span class="o">,</span> <span class="nc">Note</span><span class="o">(</span><span class="kt">var</span> <span class="n">note</span><span class="o">))</span> <span class="o">-&gt;</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Tuner active with pitch %d on note %s"</span><span class="o">,</span> <span class="n">pitch</span><span class="o">,</span> <span class="n">note</span><span class="o">);</span>
        <span class="o">};</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>Here the type arguments for the nested pattern <code class="language-plaintext highlighter-rouge">Tuner(var pitch, Note(var note))</code> are inferred. This only works with nested patterns for now; type patterns do not yet support implicit inference of type arguments. So the type pattern <code class="language-plaintext highlighter-rouge">Tuner tu</code> is always treated as a raw type pattern.</p>

<h4 id="enhanced-for-statements">Enhanced for statements</h4>

<p>Record patterns are now also allowed in enhanced <code class="language-plaintext highlighter-rouge">for</code> statements, making it easy to loop over a collection of record values and swiftly extract the components of each record:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">record</span> <span class="nf">Delay</span><span class="o">(</span><span class="kt">int</span> <span class="n">timeInMs</span><span class="o">)</span> <span class="kd">implements</span> <span class="nc">Effect</span> <span class="o">{}</span>

<span class="kd">class</span> <span class="nc">DelayPrinter</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="kt">void</span> <span class="nf">printDelays</span><span class="o">(</span><span class="nc">List</span><span class="o">&amp;</span><span class="n">lt</span><span class="o">;</span><span class="nc">Delay</span><span class="o">&amp;</span><span class="n">gt</span><span class="o">;</span> <span class="n">delays</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">for</span> <span class="o">(</span><span class="nc">Delay</span><span class="o">(</span><span class="kt">var</span> <span class="n">timeInMs</span><span class="o">)</span> <span class="o">:</span> <span class="n">delays</span><span class="o">)</span> <span class="o">{</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Delay found with timeInMs="</span> <span class="o">+</span> <span class="n">timeInMs</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<h4 id="whats-different-from-java-19-1">What’s Different From Java 19?</h4>

<p>The following changes were made to this feature compared to Java 19:</p>

<ul>
  <li>Add support for inference of type arguments of generic record patterns;</li>
  <li>Add support for record patterns to appear in the header of an enhanced for statement.</li>
</ul>

<h4 id="more-information-1">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/432">JEP 432</a>.</p>

<h2 id="from-project-loom">From Project Loom</h2>

<p>Java 20 contains three features that originated from <a href="http://openjdk.java.net/projects/loom/">Project Loom</a>:</p>

<ul>
  <li>Virtual Threads;</li>
  <li>Scoped Values;</li>
  <li>Structured Concurrency.</li>
</ul>

<blockquote>
  <p>Project Loom strives to simplify maintaining concurrent applications in Java by introducing <em>virtual threads</em> and an API for <em>structured concurrency</em>, among other things.</p>
</blockquote>

<h3 id="jep-436-virtual-threads-second-preview">JEP 436: Virtual Threads (Second Preview)</h3>

<p>Threads have been a part of Java since the very beginning, and since the start of Project Loom we’ve gradually started calling them ‘platform threads’ instead. A platform thread runs Java code on an underlying OS thread and captures the OS thread for the code’s entire lifetime. The number of platform threads is therefore limited to the number of available OS threads.</p>

<p>Modern applications, however, might need many more threads than that; when dealing with tens of thousands of requests at the same time, for example. This is where <em>virtual threads</em> come in. A virtual thread is an instance of <code class="language-plaintext highlighter-rouge">java.lang.Thread</code> that runs Java code on an underlying OS thread, but does not capture the OS thread for the code’s entire lifetime. This means that many virtual threads can run their Java code on the same OS thread, effectively sharing it. The number of virtual threads can thus be much larger than the number of available OS threads.</p>

<p>Aside from being plentiful, virtual threads are also cheap to create and dispose of. This means that a web framework, for example, can dedicate a new virtual thread to the task of handling a request and still be able to process thousands or even millions of requests at once.</p>

<h4 id="typical-use-cases">Typical Use Cases</h4>

<p>Using virtual threads does not require learning new concepts, though it may require unlearning habits developed to cope with today’s high cost of threads. Virtual threads will not only help application developers; they will also help framework designers provide easy-to-use APIs that are compatible with the platform’s design without compromising on scalability.</p>

<h4 id="creating-virtual-threads">Creating Virtual Threads</h4>

<p>Just like a platform thread, a virtual thread is an instance of <code class="language-plaintext highlighter-rouge">java.lang.Thread</code>. So you can use a virtual thread in exactly the same way as a platform thread.</p>

<p>Creating a virtual thread is a bit different, but just as easy as creating a platform thread:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">platformThread</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Thread</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="o">{</span>
    <span class="c1">// do some work in a platform thread</span>
<span class="o">});</span>
<span class="n">platformThread</span><span class="o">.</span><span class="na">start</span><span class="o">();</span>

<span class="kt">var</span> <span class="n">virtualThread</span> <span class="o">=</span> <span class="nc">Thread</span><span class="o">.</span><span class="na">startVirtualThread</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="o">{</span>
    <span class="c1">// do some work in a virtual thread</span>
<span class="o">});</span>
<span class="n">virtualThread</span><span class="o">.</span><span class="na">start</span><span class="o">();</span>
</code></pre></div></div>

<p>When your code uses the <code class="language-plaintext highlighter-rouge">ExecutorService</code> interface already, switching to virtual threads will take even less effort:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">platformThreadsExecutor</span> <span class="o">=</span> <span class="nc">Executors</span><span class="o">.</span><span class="na">newCachedThreadPool</span><span class="o">();</span>
<span class="n">platformThreadsExecutor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="o">{</span>
    <span class="c1">// do some work in a platform thread</span>
<span class="o">});</span>
<span class="n">platformThreadsExecutor</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>

<span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">virtualThreadsExecutor</span> <span class="o">=</span> <span class="nc">Executors</span><span class="o">.</span><span class="na">newVirtualThreadPerTaskExecutor</span><span class="o">())</span> <span class="o">{</span>
    <span class="n">virtualThreadsExecutor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="o">{</span>
        <span class="c1">// do some work in a virtual thread</span>
    <span class="o">});</span>
<span class="o">}</span> <span class="c1">// close() is called implicitly</span>
</code></pre></div></div>

<p>Note that the <code class="language-plaintext highlighter-rouge">ExecutorService</code> interface was  adjusted in Java 19 to extend <code class="language-plaintext highlighter-rouge">AutoCloseable</code>, so it can now be used in a try-with-resources construct.</p>

<h4 id="whats-different-from-java-19-2">What’s Different From Java 19?</h4>

<p>The feature is in the ‘second preview’ stage, to allow for more feedback. On top of that, a few API changes were made permanent and as a result are not proposed for preview any longer. This is because they involve functionality that is useful in general and is not specific to virtual threads, including:</p>

<ul>
  <li>new methods in <code class="language-plaintext highlighter-rouge">Thread</code> class:
    <ul>
      <li><code class="language-plaintext highlighter-rouge">join(Duration)</code>;</li>
      <li><code class="language-plaintext highlighter-rouge">sleep(Duration)</code>;</li>
      <li><code class="language-plaintext highlighter-rouge">threadId()</code>.</li>
    </ul>
  </li>
  <li>new methods in <code class="language-plaintext highlighter-rouge">Future</code> (to examine task state and result)</li>
  <li>the change to make <code class="language-plaintext highlighter-rouge">ExecutorService</code> extend <code class="language-plaintext highlighter-rouge">AutoCloseable</code>, so that it can be used in a try-with-resources block.</li>
</ul>

<p>On top of that, <a href="https://openjdk.org/jeps/425#java-lang-ThreadGroup">the degradations to <code class="language-plaintext highlighter-rouge">ThreadGroup</code></a> were also made permanent.</p>

<h4 id="more-information-2">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/436">JEP 436</a>.</p>

<h3 id="jep-429-scoped-values-incubator">JEP 429: Scoped Values (Incubator)</h3>

<p><em>Scoped values</em> 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.</p>

<h4 id="threadlocal">ThreadLocal</h4>

<p>Since Java 1.2 we can make use of <code class="language-plaintext highlighter-rouge">ThreadLocal</code> variables, which confine a certain value to the thread that created it.
In <a href="https://stackoverflow.com/a/817926">some cases</a> that can be a simple way to achieve thread-safety.</p>

<p>But thread-local variables also come with a few caveats. Every thread-local variable is mutable, which makes it hard to discern which component updates shared state and in what order. There’s also the risk of memory leaks, because unless you call <code class="language-plaintext highlighter-rouge">remove()</code> on the <code class="language-plaintext highlighter-rouge">ThreadLocal</code> the data is retained until it is garbage collected (which is only after the thread has terminated). And finally, thread-local variables of a parent thread can be inherited by child threads, which results in the child thread having to allocate storage for every thread-local variable previously written in the parent thread.</p>

<p>These drawbacks become more apparent now that virtual threads have been introduced, because millions of them could be active at the same time - each with their own thread-local variables - which would result in a significant memory footprint.</p>

<h4 id="scoped-values">Scoped Values</h4>

<p>Like a thread-local variable, a scoped value has multiple incarnations, one per thread. Unlike a thread-local variable, a scoped value is written once and is then immutable, and is available only for a bounded period during execution of the thread.</p>

<p>The JEP illustrates the use of scoped values with the pseudo code example below:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">final</span> <span class="kd">static</span> <span class="nc">ScopedValue</span><span class="o">&lt;...&gt;</span> <span class="no">V</span> <span class="o">=</span> <span class="nc">ScopedValue</span><span class="o">.</span><span class="na">newInstance</span><span class="o">();</span>

<span class="c1">// In some method</span>
<span class="nc">ScopedValue</span><span class="o">.</span><span class="na">where</span><span class="o">(</span><span class="no">V</span><span class="o">,</span> <span class="o">&lt;</span><span class="n">value</span><span class="o">&gt;)</span>
           <span class="o">.</span><span class="na">run</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="o">{</span> <span class="o">...</span> <span class="no">V</span><span class="o">.</span><span class="na">get</span><span class="o">()</span> <span class="o">...</span> <span class="n">call</span> <span class="n">methods</span> <span class="o">...</span> <span class="o">});</span>

<span class="c1">// In a method called directly or indirectly from the lambda expression</span>
<span class="o">...</span> <span class="no">V</span><span class="o">.</span><span class="na">get</span><span class="o">()</span> <span class="o">...</span>
</code></pre></div></div>

<p>We see that <code class="language-plaintext highlighter-rouge">ScopedValue.where(...)</code> is called, presenting a scoped value and the object to which it is to be bound. The call to <code class="language-plaintext highlighter-rouge">run(...)</code> binds the scoped value, providing an incarnation that is specific to the current thread, and then executes the lambda expression passed as argument. During the lifetime of the <code class="language-plaintext highlighter-rouge">run(...)</code> call, the lambda expression, or any method called directly or indirectly from that expression, can read the scoped value via the value’s <code class="language-plaintext highlighter-rouge">get()</code> method. After the <code class="language-plaintext highlighter-rouge">run(...)</code> method finishes, the binding is destroyed.</p>

<h4 id="typical-use-cases-1">Typical Use Cases</h4>

<p>Scoped values will be useful in all places where currently thread-local variables are used for the purpose of one-way transmission of unchanging data.</p>

<h4 id="whats-different-from-java-19-3">What’s Different From Java 19?</h4>

<p>Java 19 didn’t contain anything related to scoped values yet, so Java 20 is the first time we get to experiment with them. Note that the JEP is in the <a href="https://openjdk.org/jeps/11">incubator</a> stage, so you’ll need to add <code class="language-plaintext highlighter-rouge">--enable-preview --add-modules jdk.incubator.concurrent</code> to the command-line to be able to take the feature for a spin.</p>

<h4 id="more-information-3">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/429">JEP 429</a>.</p>

<h3 id="jep-437-structured-concurrency-second-incubator">JEP 437: Structured Concurrency (Second Incubator)</h3>

<p>Java’s current implementation of concurrency is <em>unstructured</em>, which can make error handling and cancellation with multiple tasks a challenge. When multiple tasks are started up asynchronously, we currently aren’t able to cancel the remaining tasks once the first task returns an error.</p>

<p>Let’s illustrate this point with a code example from the JEP:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Response</span> <span class="nf">handle</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">ExecutionException</span><span class="o">,</span> <span class="nc">InterruptedException</span> <span class="o">{</span>
    <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span>  <span class="n">user</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">findUser</span><span class="o">());</span>
    <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">order</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="na">submit</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">fetchOrder</span><span class="o">());</span>
    <span class="nc">String</span> <span class="n">theUser</span> <span class="o">=</span> <span class="n">user</span><span class="o">.</span><span class="na">get</span><span class="o">();</span>   <span class="c1">// Join findUser</span>
    <span class="kt">int</span> <span class="n">theOrder</span> <span class="o">=</span> <span class="n">order</span><span class="o">.</span><span class="na">get</span><span class="o">();</span>  <span class="c1">// Join fetchOrder</span>
    <span class="k">return</span> <span class="k">new</span> <span class="nf">Response</span><span class="o">(</span><span class="n">theUser</span><span class="o">,</span> <span class="n">theOrder</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<p>When the <code class="language-plaintext highlighter-rouge">user.get()</code> call results in an error, there is no way for us to cancel the second task when we want to prevent getting a result that won’t be used anyway. 
Though when we would rewrite this code to use just a single thread, the situation would become a lot simpler:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Response</span> <span class="nf">handle</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">IOException</span> <span class="o">{</span>
    <span class="nc">String</span> <span class="n">theUser</span> <span class="o">=</span> <span class="n">findUser</span><span class="o">();</span>
    <span class="kt">int</span> <span class="n">theOrder</span> <span class="o">=</span> <span class="n">fetchOrder</span><span class="o">();</span>
    <span class="k">return</span> <span class="k">new</span> <span class="nf">Response</span><span class="o">(</span><span class="n">theUser</span><span class="o">,</span> <span class="n">theOrder</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<p>See? Here we would be able to prevent the second call once the first one has failed.</p>

<p>In general, multithreaded programming in Java would be easier, more reliable, and more observable if the parent-child relationships between tasks and their subtasks were expressed syntactically — just as for single-threaded code. The syntactic structure would delineate the lifetimes of subtasks and enable a runtime representation of the inter-thread hierarchy, enabling error propagation and cancellation as well as meaningful observation of the concurrent program.</p>

<p>Enter <em>structured concurrency</em>. We’ve now rewritten the code example to make use of the new <code class="language-plaintext highlighter-rouge">StructuredTaskScope</code> API:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Response</span> <span class="nf">handle</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">ExecutionException</span><span class="o">,</span> <span class="nc">InterruptedException</span> <span class="o">{</span>
  <span class="k">try</span> <span class="o">(</span><span class="kt">var</span> <span class="n">scope</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StructuredTaskScope</span><span class="o">.</span><span class="na">ShutdownOnFailure</span><span class="o">())</span> <span class="o">{</span>
      <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span>  <span class="n">user</span>  <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">findUser</span><span class="o">());</span>
      <span class="nc">Future</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">order</span> <span class="o">=</span> <span class="n">scope</span><span class="o">.</span><span class="na">fork</span><span class="o">(()</span> <span class="o">-&gt;</span> <span class="n">fetchOrder</span><span class="o">());</span>

      <span class="n">scope</span><span class="o">.</span><span class="na">join</span><span class="o">();</span>           <span class="c1">// Join both forks</span>
      <span class="n">scope</span><span class="o">.</span><span class="na">throwIfFailed</span><span class="o">();</span>  <span class="c1">// ... and propagate errors</span>

      <span class="c1">// Here, both forks have succeeded, so compose their results</span>
      <span class="k">return</span> <span class="k">new</span> <span class="nf">Response</span><span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">resultNow</span><span class="o">(),</span> <span class="n">order</span><span class="o">.</span><span class="na">resultNow</span><span class="o">());</span>
  <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>In structured concurrency, subtasks work on behalf of a task. The task awaits the subtasks’ results and monitors them for failures. The <code class="language-plaintext highlighter-rouge">StructuredTaskScope</code> class allows developers to structure a task as a family of concurrent subtasks, and to coordinate them as a unit. Subtasks are executed in their own threads by forking them individually and then joining them as a unit and, possibly, cancelling them as a unit. The subtasks’ successful results or exceptions are aggregated and handled by the parent task.</p>

<p>In contrast to the original example, understanding the lifetimes of the threads involved here is easy. Under all conditions their lifetimes are confined to a lexical scope, namely the body of the try-with-resources statement. Furthermore, the use of <code class="language-plaintext highlighter-rouge">StructuredTaskScope</code> ensures a number of valuable properties:</p>

<ul>
  <li>
    <p><em>Error handling with short-circuiting</em>. If one of the subtasks fail, the other is cancelled if it has not yet completed. This is managed by the cancellation policy implemented by <code class="language-plaintext highlighter-rouge">ShutdownOnFailure</code>; other policies like <code class="language-plaintext highlighter-rouge">ShutdownOnSuccess</code> are also available.</p>
  </li>
  <li>
    <p><em>Cancellation propagation</em>. If the thread running <code class="language-plaintext highlighter-rouge">handle()</code> is interrupted before or during the call to <code class="language-plaintext highlighter-rouge">join()</code>, both forks are cancelled automatically when the thread exits the scope.</p>
  </li>
  <li>
    <p><em>Clarity</em> — The above code has a clear structure: Set up the subtasks, wait for them to either complete or be cancelled, and then decide whether to succeed (and process the results of the child tasks, which are already finished) or fail (and the subtasks are already finished, so there is nothing more to clean up).</p>
  </li>
</ul>

<p>By the way: it is by no means coincidental that structured concurrency is coming to Java at the same time as virtual threads. Modern Java programs will likely use an abundance of threads, and they need to be correctly and robustly coordinated. Structured concurrency can provide exactly that, while also enabling observability tools to display threads as they are understood by the developer.</p>

<h4 id="whats-different-from-java-19-4">What’s Different From Java 19?</h4>

<p>The situation is roughly the same as how it was in Java 19 (see <a href="https://openjdk.org/jeps/428">JEP 428</a>).
The only change is an update to <code class="language-plaintext highlighter-rouge">StructuredTaskScope</code> to make it support the inheritance of <a href="#jep-429-scoped-values-incubator">scoped values</a> by threads created in a task scope. This streamlines the sharing of immutable data across threads. Again, note that the JEP is in the <a href="https://openjdk.org/jeps/11">incubator</a> stage, so you’ll need to add <code class="language-plaintext highlighter-rouge">--enable-preview --add-modules jdk.incubator.concurrent</code> to the command-line to be able to take the feature for a spin.</p>

<h4 id="more-information-4">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/437">JEP 437</a>.</p>

<h2 id="from-project-panama">From Project Panama</h2>

<p>Java 20 contains two features that originated from <a href="http://openjdk.java.net/projects/panama/">Project Panama</a>:</p>

<ul>
  <li>Foreign Function &amp; Memory API;</li>
  <li>Vector API.</li>
</ul>

<blockquote>
  <p>Project Panama aims to improve the connection between the JVM and foreign (non-Java) libraries.</p>
</blockquote>

<h3 id="jep-434-foreign-function--memory-api-second-preview">JEP 434: Foreign Function &amp; Memory API (Second Preview)</h3>

<p>Java programs have always had the option of interacting with code and data outside of the Java runtime.
We could use the <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jni/">Java Native Interface</a> (JNI) to invoking foreign functions (outside of the JVM but on the same machine).
And accessing foreign memory (outside of the JVM, so off-heap) was possible using either the <a href="https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/nio/ByteBuffer.html">ByteBuffer API</a> or the <a href="https://github.com/openjdk/jdk/blob/master/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java">sun.misc.Unsafe API</a>.</p>

<p>However, these three mechanisms all come with their own drawbacks, which is why a more modern API is now proposed to support foreign functions and foreign memory in a better way.</p>

<blockquote>
  <p>Performance-critical libraries like <a href="https://github.com/tensorflow/tensorflow">Tensorflow</a>, <a href="https://lucene.apache.org/">Lucene</a> or <a href="https://netty.io/">Netty</a> typically rely on using foreign memory, because they need more control over the memory they use to prevent the cost and unpredictability that comes with garbage collection.</p>
</blockquote>

<h4 id="code-example">Code Example</h4>

<p>In order to demonstrate the new API, <a href="https://openjdk.org/jeps/434">JEP 434</a> lists a code example that obtains a method handle for a C library function <code class="language-plaintext highlighter-rouge">radixsort</code> and then uses it to sort four strings that start out as Java array elements:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// 1. Find foreign function on the C library path</span>
<span class="nc">Linker</span> <span class="n">linker</span>          <span class="o">=</span> <span class="nc">Linker</span><span class="o">.</span><span class="na">nativeLinker</span><span class="o">();</span>
<span class="nc">SymbolLookup</span> <span class="n">stdlib</span>    <span class="o">=</span> <span class="n">linker</span><span class="o">.</span><span class="na">defaultLookup</span><span class="o">();</span>
<span class="nc">MethodHandle</span> <span class="n">radixsort</span> <span class="o">=</span> <span class="n">linker</span><span class="o">.</span><span class="na">downcallHandle</span><span class="o">(</span><span class="n">stdlib</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="s">"radixsort"</span><span class="o">),</span> <span class="o">...);</span>
<span class="c1">// 2. Allocate on-heap memory to store four strings</span>
<span class="nc">String</span><span class="o">[]</span> <span class="n">javaStrings</span> <span class="o">=</span> <span class="o">{</span> <span class="s">"mouse"</span><span class="o">,</span> <span class="s">"cat"</span><span class="o">,</span> <span class="s">"dog"</span><span class="o">,</span> <span class="s">"car"</span> <span class="o">};</span>
<span class="c1">// 3. Use try-with-resources to manage the lifetime of off-heap memory</span>
<span class="k">try</span> <span class="o">(</span><span class="nc">Arena</span> <span class="n">offHeap</span> <span class="o">=</span> <span class="nc">Arena</span><span class="o">.</span><span class="na">openConfined</span><span class="o">())</span> <span class="o">{</span>
    <span class="c1">// 4. Allocate a region of off-heap memory to store four pointers</span>
    <span class="nc">MemorySegment</span> <span class="n">pointers</span> <span class="o">=</span> <span class="n">offHeap</span><span class="o">.</span><span class="na">allocateArray</span><span class="o">(</span><span class="nc">ValueLayout</span><span class="o">.</span><span class="na">ADDRESS</span><span class="o">,</span> <span class="n">javaStrings</span><span class="o">.</span><span class="na">length</span><span class="o">);</span>
    <span class="c1">// 5. Copy the strings from on-heap to off-heap</span>
    <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">javaStrings</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="nc">MemorySegment</span> <span class="n">cString</span> <span class="o">=</span> <span class="n">offHeap</span><span class="o">.</span><span class="na">allocateUtf8String</span><span class="o">(</span><span class="n">javaStrings</span><span class="o">[</span><span class="n">i</span><span class="o">]);</span>
        <span class="n">pointers</span><span class="o">.</span><span class="na">setAtIndex</span><span class="o">(</span><span class="nc">ValueLayout</span><span class="o">.</span><span class="na">ADDRESS</span><span class="o">,</span> <span class="n">i</span><span class="o">,</span> <span class="n">cString</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="c1">// 6. Sort the off-heap data by calling the foreign function</span>
    <span class="n">radixsort</span><span class="o">.</span><span class="na">invoke</span><span class="o">(</span><span class="n">pointers</span><span class="o">,</span> <span class="n">javaStrings</span><span class="o">.</span><span class="na">length</span><span class="o">,</span> <span class="nc">MemorySegment</span><span class="o">.</span><span class="na">NULL</span><span class="o">,</span> <span class="sc">'\0'</span><span class="o">);</span>
    <span class="c1">// 7. Copy the (reordered) strings from off-heap to on-heap</span>
    <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">javaStrings</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="nc">MemorySegment</span> <span class="n">cString</span> <span class="o">=</span> <span class="n">pointers</span><span class="o">.</span><span class="na">getAtIndex</span><span class="o">(</span><span class="nc">ValueLayout</span><span class="o">.</span><span class="na">ADDRESS</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
        <span class="n">javaStrings</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="n">cString</span><span class="o">.</span><span class="na">getUtf8String</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span> <span class="c1">// 8. All off-heap memory is deallocated here</span>
<span class="k">assert</span> <span class="nc">Arrays</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">javaStrings</span><span class="o">,</span> <span class="k">new</span> <span class="nc">String</span><span class="o">[]</span> <span class="o">{</span><span class="s">"car"</span><span class="o">,</span> <span class="s">"cat"</span><span class="o">,</span> <span class="s">"dog"</span><span class="o">,</span> <span class="s">"mouse"</span><span class="o">});</span>  <span class="c1">// true</span>
</code></pre></div></div>

<p>Let’s look at some of the types this code uses in more detail to get a rough idea of their function and purpose within the Foreign Function &amp; Memory API:</p>

<dl>
  <dt><code class="language-plaintext highlighter-rouge">Linker</code></dt>
  <dd>Provides access to foreign functions from Java code, and access to Java code from foreign functions. It allows Java code to link against foreign functions, via <em>downcall method handles</em>. It also allows foreign functions to call Java method handles, via the generation of <em>upcall stubs</em>. See the <a href="https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/foreign/Linker.html">JavaDoc</a> of this type for more information.</dd>
  <dt><code class="language-plaintext highlighter-rouge">SymbolLookup</code></dt>
  <dd>Retrieves the address of a symbol in one or more libraries. See the <a href="https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/foreign/SymbolLookup.html">JavaDoc</a> of this type for more information.</dd>
  <dt><code class="language-plaintext highlighter-rouge">Arena</code></dt>
  <dd>Controls the lifecycle of memory segments. An arena has a scope, called the arena scope. When the arena is closed, the arena scope is no longer alive. As a result, all the segments associated with the arena scope are invalidated, their backing memory regions are deallocated (where applicable) and can no longer be accessed after the arena is closed. See the <a href="https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/foreign/Arena.html">JavaDoc</a> of this type for more information.</dd>
  <dt><code class="language-plaintext highlighter-rouge">MemorySegment</code></dt>
  <dd>Provides access to a contiguous region of memory. There are two kinds of memory segments: <em>heap segments</em> (inside the Java memory heap) and <em>native segments</em> (outside of the Java memory heap). See the <a href="https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/foreign/MemorySegment.html">JavaDoc</a> of this type for more information.</dd>
  <dt><code class="language-plaintext highlighter-rouge">ValueLayout</code></dt>
  <dd>Models values of basic data types, such as <em>integral</em> values, <em>floating-point</em> values and <em>address</em> values. On top of that, it defines useful value layout constants for Java primitive types and addresses. See the <a href="https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/foreign/ValueLayout.html">JavaDoc</a> of this type for more information.</dd>
</dl>

<h4 id="whats-different-from-java-19-5">What’s Different From Java 19?</h4>

<p>In Java 19, this feature was in its first preview status (in the form of <a href="https://openjdk.org/jeps/424">JEP 424</a>), so the language feature was complete and developer feedback was gathered. Based on this feedback the following changes happened to Java 20:</p>

<ul>
  <li>The <code class="language-plaintext highlighter-rouge">MemorySegment</code> and <code class="language-plaintext highlighter-rouge">MemoryAddress</code> abstractions were unified (memory addresses are now modeled by zero-length memory segments);</li>
  <li>The sealed <code class="language-plaintext highlighter-rouge">MemoryLayout</code> hierarchy was enhanced to facilitate usage with <a href="http://localhost:4000/2023/03/21/whats-new-in-java-20/#jep-433-pattern-matching-for-switch-fourth-preview">pattern matching for switch</a>;</li>
  <li><code class="language-plaintext highlighter-rouge">MemorySession</code> has been split into <code class="language-plaintext highlighter-rouge">Arena</code> and <code class="language-plaintext highlighter-rouge">SegmentScope</code> to facilitate sharing segments across maintenance boundaries.</li>
</ul>

<h4 id="more-information-5">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/434">JEP 434</a>.</p>

<h3 id="jep-438-vector-api-fifth-incubator">JEP 438: Vector API (Fifth Incubator)</h3>

<p>The Vector API will make it possible to express vector computations that reliably compile at runtime to optimal vector instructions. 
This means that these computations will significantly outperform equivalent scalar computations on the supported CPU architectures (x64 and AArch64).</p>

<h4 id="vector-computations-help-me-out-here">Vector Computations? Help Me Out Here!</h4>

<p>A <em>vector computation</em> is a mathematical operation on one or more one-dimensional matrices of an arbitrary length. Think of a vector as an array with a dynamic length. Furthermore, the elements in the vector can be accessed in constant time via indices, just like with an array.</p>

<p>In the past, Java programmers could only program such computations at the assembly-code level. But now that modern CPUs support advanced <a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">SIMD</a> features (Single Instruction, Multiple Data), it becomes more important to take advantage of the performance gains that SIMD instructions and multiple lanes operating in parallel can bring. The Vector API brings that possibility closer to the Java programmer.</p>

<h4 id="code-example-1">Code Example</h4>

<p>Here is a code example (taken from the JEP) that compares a simple scalar computation over elements of arrays with its equivalent using the Vector API:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">scalarComputation</span><span class="o">(</span><span class="kt">float</span><span class="o">[]</span> <span class="n">a</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">b</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">c</span><span class="o">)</span> <span class="o">{</span>
   <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="n">c</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">+</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">])</span> <span class="o">*</span> <span class="o">-</span><span class="mf">1.0f</span><span class="o">;</span>
   <span class="o">}</span>
<span class="o">}</span>

<span class="kd">static</span> <span class="kd">final</span> <span class="nc">VectorSpecies</span><span class="o">&lt;</span><span class="nc">Float</span><span class="o">&gt;</span> <span class="no">SPECIES</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">SPECIES_PREFERRED</span><span class="o">;</span>

<span class="kt">void</span> <span class="nf">vectorComputation</span><span class="o">(</span><span class="kt">float</span><span class="o">[]</span> <span class="n">a</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">b</span><span class="o">,</span> <span class="kt">float</span><span class="o">[]</span> <span class="n">c</span><span class="o">)</span> <span class="o">{</span>
    <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
    <span class="kt">int</span> <span class="n">upperBound</span> <span class="o">=</span> <span class="no">SPECIES</span><span class="o">.</span><span class="na">loopBound</span><span class="o">(</span><span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">);</span>
    <span class="k">for</span> <span class="o">(;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">upperBound</span><span class="o">;</span> <span class="n">i</span> <span class="o">+=</span> <span class="no">SPECIES</span><span class="o">.</span><span class="na">length</span><span class="o">())</span> <span class="o">{</span>
        <span class="c1">// FloatVector va, vb, vc;</span>
        <span class="kt">var</span> <span class="n">va</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">fromArray</span><span class="o">(</span><span class="no">SPECIES</span><span class="o">,</span> <span class="n">a</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
        <span class="kt">var</span> <span class="n">vb</span> <span class="o">=</span> <span class="nc">FloatVector</span><span class="o">.</span><span class="na">fromArray</span><span class="o">(</span><span class="no">SPECIES</span><span class="o">,</span> <span class="n">b</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
        <span class="kt">var</span> <span class="n">vc</span> <span class="o">=</span> <span class="n">va</span><span class="o">.</span><span class="na">mul</span><span class="o">(</span><span class="n">va</span><span class="o">)</span>
                   <span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">vb</span><span class="o">.</span><span class="na">mul</span><span class="o">(</span><span class="n">vb</span><span class="o">))</span>
                   <span class="o">.</span><span class="na">neg</span><span class="o">();</span>
        <span class="n">vc</span><span class="o">.</span><span class="na">intoArray</span><span class="o">(</span><span class="n">c</span><span class="o">,</span> <span class="n">i</span><span class="o">);</span>
    <span class="o">}</span>
    <span class="k">for</span> <span class="o">(;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">a</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
        <span class="n">c</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">=</span> <span class="o">(</span><span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">a</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">+</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">]</span> <span class="o">*</span> <span class="n">b</span><span class="o">[</span><span class="n">i</span><span class="o">])</span> <span class="o">*</span> <span class="o">-</span><span class="mf">1.0f</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<p>From the perspective of the Java developer, this is just another way of expressing scalar computations. It might come across as being slightly more verbose, but on the other hand it can bring spectacular performance gains.</p>

<h4 id="typical-use-cases-2">Typical Use Cases</h4>

<p>The Vector API provides a way to write complex vector algorithms in Java that perform extremely well, such as vectorized <code class="language-plaintext highlighter-rouge">hashCode</code> implementations or specialized array comparisons. Numerous domains can benefit from this, including machine learning, linear algebra, encryption, text processing, finance, and code within the JDK itself.</p>

<h4 id="whats-different-from-java-19-6">What’s Different From Java 19?</h4>

<p>Aside from a small set of bug fixes and performance enhancements, the alignment of this feature with <a href="https://openjdk.org/projects/valhalla/">Project Valhalla</a> is the biggest difference with Java 19. And it’s one that makes a lot of sense, as both the Vector API and Project Valhalla focus on performance improvements.</p>

<blockquote>
  <p>Recall that Project Valhalla’s aim is to augment the Java object model with value objects and user-defined primitives, combining the abstractions of object-oriented programming with the performance characteristics of simple primitives.</p>
</blockquote>

<p>Once the features of Project Valhalla are available, the Vector API will be adapted to make use of value objects and by that time it will be promoted to a preview feature.</p>

<h4 id="more-information-6">More Information</h4>

<p>For more information on this feature, see <a href="https://openjdk.org/jeps/438">JEP 438</a>.</p>

<h2 id="final-thoughts">Final thoughts</h2>

<p>So, these are exciting times for Java programmers! The language is evolving at a fast pace, and new features are being published alongside each other in a coordinated way. On top of that, they tend to be more focused on making the best use of modern hardware, which gives Java a very good chance of remaining relevant in this day and age. So what are you still waiting for? Take <a href="https://jdk.java.net/20/">Java 20</a> for a spin!</p>]]></content><author><name>Hanno Embregts</name></author><category term="java" /><summary type="html"><![CDATA[This will be a good day, because it’s Java 20 release day! It’s been six months since Java 19 was released, and so it’s time for another fresh wave of Java features. This post will take you on a tour through all JEPs that come with this release and give you a brief introduction of each one of them. Where applicable the differences with Java 19 are highlighted and a few typical use cases are provided, so that you’ll be more than ready to use these features after you’ve finished reading!]]></summary></entry><entry><title type="html">Exploring sustainability in tech (without the guilt-trips)</title><link href="https://hanno.codes/2022/11/14/exploring-sustainability-in-tech/" rel="alternate" type="text/html" title="Exploring sustainability in tech (without the guilt-trips)" /><published>2022-11-14T18:00:00+00:00</published><updated>2022-11-14T18:00:00+00:00</updated><id>https://hanno.codes/2022/11/14/exploring-sustainability-in-tech</id><content type="html" xml:base="https://hanno.codes/2022/11/14/exploring-sustainability-in-tech/"><![CDATA[<p>Climate change is a thing that affects us all. As developers, we are in a unique position to help do something about this. After all, the whole world runs on computers these days, and computers consume energy. We, developers, program these computers, and the decisions that we make have consequences beyond the business domain we code for. Also, as employed people living in Europe or North-America, we belong to the top 10% of richest people on the planet.</p>

<p><img src="/assets/images/blog/2022-11-14-exploring-sustainability-in-tech/IMG_1142.JPG" alt="Panel at Devoxx" /></p>

<p>(source: Joey Bakker)</p>

<p>But what <em>can</em> we do specifically? It’s not often clear. After a discussion on Twitter, we (<a href="https://twitter.com/hannotify">Hanno Embregts</a>, <a href="https://twitter.com/jlengrand">Julien Lengrand-Lambert</a>, <a href="https://twitter.com/jhkuperus">Jan-Hendrik Kuperus</a> and <a href="https://twitter.com/jqno">Jan Ouwens</a>) discovered we all have ideas about what we can do. Julien even has a <a href="https://www.youtube.com/watch?v=umQby6H50xI">conference talk</a> on the subject. We want to know how we can make the most impact, and we know that we can’t do it alone.</p>

<p>We figured it was a good idea to host a panel about it: both to get more people involved in the conversation and to learn from them ourselves. The most important rule of such a panel? <strong>No guilt-tripping</strong>! We all do our best, and ultimately, that’s all we can do. Participating in a panel like this one can serve as an inspiration to do even better.</p>

<p><img src="/assets/images/blog/2022-11-14-exploring-sustainability-in-tech/img_1198.jpg" alt="Panel at J-Fall" /></p>

<p>(source: Joey Bakker)</p>

<p>We’ve been fortunate to host this panel twice so far: once as a Birds-of-a-Feather session at Devoxx Belgium, and once at J-Fall in the Netherlands, both in 2022. Both times, we first set the stage by presenting some information about climate change, to get all attendees on the same page. Then, we opened up the floor for discussion, based around three main themes: developer sustainability, infra sustainability, and personal sustainability. Both times, a lively discussion followed in which many great ideas were shared, and the hour just flew by. We were even able to take some learnings from Devoxx with us to the J-Fall panel.</p>

<p><img src="/assets/images/blog/2022-11-14-exploring-sustainability-in-tech/IMG_1144.JPG" alt="Panel at Devoxx" /></p>

<p>(source: Joey Bakker)</p>

<p>Here are a few things that resonated most with the attendees at both conferences, grouped by theme.</p>

<h2 id="setting-the-stage">Setting the stage</h2>

<p><img src="/assets/images/blog/2022-11-14-exploring-sustainability-in-tech/semi_rad.jpg" alt="Climate change: a timeline" /> (source: <a href="https://twitter.com/semi_rad/status/1055192820124856320">@semi_rad on Twitter</a>)</p>

<ul>
  <li>We started with this image and did a show of hands to see where everybody thinks we stand right now. Most were at ‘Oops’, though several were at ‘F°ck’ as well. Nobody thought we were in the first two categories.</li>
  <li>Xkcd’s <a href="https://xkcd.com/1732/">Earth Temperature Timeline</a> made an impact. It also happens to be a nice example of what developers can do that no-one else can: Randall Munroe, the comic’s creator, has modified his server’s configuration so that anyone visiting from a US Government IP is redirected to this particular comic, regardless of which of his 2600+ other comics was requested.</li>
</ul>

<h2 id="developer-sustainability">Developer sustainability</h2>

<ul>
  <li>
    <p>The most important choice a developer can make, is where they work. Would you want to work for oil companies, airlines, or banks with dubious investment portfolios?
<img src="/assets/images/blog/2022-11-14-exploring-sustainability-in-tech/greenlanguages.png" alt="Green programming languages" /> (source: <a href="https://sites.google.com/view/energy-efficiency-languages">Energy Efficiency across Programming Languages: How does Energy, Time and Memory Relate?</a>)</p>
  </li>
  <li>Choosing the right programming language matters. However, while the research behind this table is interesting, we found several factors outside the scope of this research that would contribute. For instance, how does the developer workflow of compiling and running tests factor into this? Also, while Python is near the bottom of this list, the really resource-intensive machine learning stuff it’s currently popular for, is delegated to heavily optimized C-libraries; Python is merely the glue. Ultimately, no-one was convinced to switch to C or Rust.</li>
  <li>Someone suggested spending more time on design up-front, since spending more time on design might mean less time spent in energy-intensive compile-test-debug loops.</li>
  <li>Turn things off after office hours: the amount of energy wasted on idling test environments is probably huge. One attendee told a story about a school saving €12k a year in power bills by running a script that automatically turns off all computers and peripherals outside office hours.</li>
</ul>

<h2 id="infra-sustainability">Infra sustainability</h2>

<ul>
  <li>It’s hard to measure the carbon footprint of an app. The closest approximation seems to be the monthly bill at the cloud provider: the lower it is, the lower your footprint will be as well. However, one attendee suggested <a href="https://www.cloudcarbonfootprint.org/">Cloud Carbon Footprint</a>, which calculates the footprint of your cloud app and suggests ways to improve it.</li>
</ul>

<p><img src="/assets/images/blog/2022-11-14-exploring-sustainability-in-tech/sunday.jpg" alt="A christian news website closed on Sunday" /> 
(source: <a href="https://www.rd.nl">Reformatorisch Dagblad</a>, screenshots by Jan Ouwens)</p>

<ul>
  <li>In addition to shutting down our personal equipment after office hours, we can think about shutting down apps. Does your corporate app really need to run 24/7, or have many <a href="https://en.wikipedia.org/wiki/High_availability#%22Nines%22">nines of uptime</a>? Some Christian newspapers and web shops in The Netherlands turn their websites off on Sundays. While they do it for religious reasons, we can do it for other reasons, such as reducing energy consumption and reducing infrastructure complexity. When applied where it makes sense, and when communicated properly, your customers and users will probably understand.</li>
  <li>With the prevalence of solar power nowadays, maybe we should rethink our nightly builds, and run them during the day instead. Or as someone pointed out: it’s always afternoon <em>somewhere</em>; just run the build in a region where the sun is out!</li>
  <li>Either way, make sure to cache your builds. If you let Maven download all of your projects dependencies on every build, you’ll undo a lot of effort to make the build more sustainable.</li>
  <li>If possible, take footprint into account when choosing your cloud provider. If you go for one of the Big Three, try to find out what sustainability measures they take in the data center closest to your users. Or you can look at smaller providers that are more sustainable. For instance, <a href="https://www.leaf.cloud/">LeafCloud</a> in The Netherlands adopted a decentralized approach by placing its servers in various buildings (such as hotels, nursing homes and swimming pools) scattered across the country. The heat generated by those servers is then used directly to heat the building where the servers are located.</li>
</ul>

<h2 id="personal-sustainability">Personal sustainability</h2>

<p><img src="/assets/images/blog/2022-11-14-exploring-sustainability-in-tech/co2-emissions-from-passenger-transport.jpg" alt="CO2 emissions from passenger transport graph" /> 
(source: <a href="https://www.eea.europa.eu/media/infographics/co2-emissions-from-passenger-transport/view">European Environment Agency</a>)</p>

<ul>
  <li>The way we travel makes a big impact. One attendee at Devoxx received applause when he casually mentioned he had travelled to Antwerp from Switzerland by bicyle! One J-Fall attendee mentioned he traveled by train from another country, but was disappointed how it not only takes longer, but is also about 4 times more expensive, which doesn’t make sense.</li>
  <li>There was a discussion about air travel at J-Fall. We, the panelists, don’t want to tell people not to do it, and an attendee asked why not, since it’s one of the largest contributors to CO2 emission an individual can have. We decided that it’s a personal choice that everybody needs to make. If anything, it’s something for politicians to discourage and disincentivize. If politicians don’t move fast enough, it’s easy to call a political party and ask them questions, or even to join them and try to make a difference.</li>
  <li>80% of CO2 emissions for a device such as a phone, tablet or laptop are spent during production. The best way to scale down is by buying less things, and keeping them longer. Of course it’s ok to buy these things, but take quality into account: if you spend a bit more up front, you can make it last longer, which reduces emissions.</li>
</ul>

<h2 id="other">Other</h2>

<p><img src="/assets/images/blog/2022-11-14-exploring-sustainability-in-tech/img_1200.jpg" alt="Panel at J-Fall" /></p>

<p>(source: Joey Bakker)</p>

<ul>
  <li>We need to motivate other people to help, but how can we do this? We could think of only four ways: giving financial incentives, which is something for governments to do; providing a convenient way to change behavior, which is something companies (or individuals within them) can do; or … guilt-tripping people, despite the main rule of the session. The best way, however, seems to be to inspire.</li>
  <li>For instance, one of the attendees at J-Fall represented a large company that was also a sponsor of the event. She felt inspired to choose only sustainable events, from now on.</li>
  <li>Some people complained that J-Fall itself could make some improvements to become more sustainable. The lunch contained a lot of packaging and foods that not everybody wanted to eat, leading to a lot of waste. It turns out that the lunch break, like every other session, could be rated and commented on, which we all subsequently did. Hopefully this will lead to some improvements in this area next year!</li>
</ul>

<h2 id="conclusion">Conclusion</h2>

<p><img src="/assets/images/blog/2022-11-14-exploring-sustainability-in-tech/IMG_1149.JPG" alt="Panel at Devoxx" /></p>

<p>(source: Joey Bakker)</p>

<p>All these ideas are great, but it’s still interesting to see some numbers: what’s the impact of working for an oil company versus not running builds at night, for instance? For now, we leave those questions unanswered, as these sessions were mainly intended to raise awareness and get people involved. We’ll try to work on these numbers in the future.</p>

<p>After the sessions, most of the attendees had a takeaway to look into or implement right away. I, for one, have been taking the train instead of the car more often. In that sense, the sessions have been great at inspiring us to do better, rather than guilt-tripping us into it!</p>

<blockquote>
  <p>Cross-posted with permission. The original post is at <a href="https://blog.yoink.nl/posts/2022/11/14/exploring-sustainability-in-tech.html">https://blog.yoink.nl/posts/2022/11/14/exploring-sustainability-in-tech.html</a></p>
</blockquote>]]></content><author><name>Hanno Embregts</name></author><category term="sustainability" /><summary type="html"><![CDATA[Climate change is a thing that affects us all. As developers, we are in a unique position to help do something about this. After all, the whole world runs on computers these days, and computers consume energy. We, developers, program these computers, and the decisions that we make have consequences beyond the business domain we code for. Also, as employed people living in Europe or North-America, we belong to the top 10% of richest people on the planet.]]></summary></entry></feed>