Java 26 Features: All 10 JDK 26 JEPs with Code Examples

Java 26 (JDK 26) shipped on 17 March 2026 as a non-LTS release with 10 JEPs. This overview lists every JEP with its status and shows short, runnable examples for HTTP/3, final field warnings, the AOT cache with ZGC and the preview APIs.

Diagram grouping the 10 JDK 26 JEPs into final, preview, incubator and removal boxes

The main Java 26 features are HTTP/3 support in the built-in HttpClient and a warning when reflection changes a final field. JDK 26 shipped on 17 March 2026 with 10 JEPs (JDK Enhancement Proposals). Four of them are final. Most of the others are preview APIs that come back from Java 25 with changes.

JDK 26 is not an LTS (long-term support) release, so Oracle stopped updating it when Java 27 shipped.

1. When Java 26 Shipped and What Its 10 JEPs Are

JDK 26 reached general availability on 17 March 2026, six months after Java 25. Java 27 replaced it on 15 September 2026. Long-lived production apps stay on Java 25, the current LTS, until Java 29 in September 2027.

A preview API is not final yet and needs –enable-preview when we compile and when we run. An incubator module is an earlier stage and needs –add-modules.

JEPFeatureStatus in JDK 26In one line
500Prepare to Make Final Mean FinalFinalWarns when reflection changes a final field
504Remove the Applet APIRemovalDeletes java.applet and javax.swing.JApplet
516Ahead-of-Time Object Caching with Any GCFinalMakes the AOT startup cache work with ZGC too
517HTTP/3 for the HTTP Client APIFinalAdds HttpClient.Version.HTTP_3 as an opt-in protocol
522G1 GC: Improve Throughput by Reducing SynchronizationFinalMakes the default G1 garbage collector faster
524PEM Encodings of Cryptographic ObjectsSecond previewConverts keys and certificates to and from PEM text
525Structured ConcurrencySixth previewRuns related subtasks as one unit with StructuredTaskScope
526Lazy ConstantsSecond previewReplaces StableValue with LazyConstant
529Vector APIEleventh incubatorRuns math on many values at once with CPU vector instructions
530Primitive Types in Patterns, instanceof, and switchFourth previewAllows int, double and other primitives in patterns

Grouped by status, the same JEPs show that only four of them are ready for production code.

Diagram grouping the 10 JDK 26 JEPs into final, preview, incubator and removal boxes
Four of the 10 JDK 26 JEPs are final; the four preview APIs and the Vector API need extra flags.

2. Final Java 26 Features We Can Use Without Flags

The four final JEPs need no extra flags. HTTP/3 and the final field warning change what our code sees. The other two only make the JVM faster. The examples run on JDK 26 (Temurin 26.0.2.1) with Maven 3.9.16 and JUnit 6.1.3, and the project with a test for each feature is on GitHub.

2.1. Warnings When Reflection Changes a final Field (JEP 500)

Since JDK 5, deep reflection (reflection that skips the normal access checks) can change a final field with Field.setAccessible(true) and Field.set(). Some serialization libraries still do this. In Java 26 the change still works, but the JVM prints a warning the first time code in a module does it. A future release will throw IllegalAccessException instead, so JEP 500 gives us time to find that code.

For example, the Recipe class has a final int servings field that its constructor sets.

Recipe soup = new Recipe(2);                                    // servings = 2
Field servings = Recipe.class.getDeclaredField("servings");
servings.setAccessible(true);
servings.set(soup, 4);                                          // servings = 4, plus a WARNING on stderr

The warning names the field and the calling class. It also suggests –enable-final-field-mutation=ALL-UNNAMED, which allows the change without a warning for code on the class path. To find the code that will break later, we run our tests with –illegal-final-field-mutation=deny, which makes Field.set() throw IllegalAccessException.

2.2. HTTP/3 in java.net.http.HttpClient (JEP 517)

HTTP/3 is the newest version of HTTP. It runs over QUIC, a protocol that uses UDP instead of TCP. Java 26 adds HttpClient.Version.HTTP_3 to the HttpClient from Java 11, which supported HTTP/1.1 and HTTP/2. HTTP/2 stays the default, so we opt in on the client or on a single request.

HttpClient client = HttpClient.newBuilder()
        .version(HttpClient.Version.HTTP_3)
        .connectTimeout(Duration.ofSeconds(5))
        .build();
HttpRequest request = HttpRequest.newBuilder(URI.create("https://openjdk.org/"))
        .timeout(Duration.ofSeconds(10))
        .GET()
        .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
HttpClient.Version used = response.version();      // HTTP_3, or HTTP_2 when UDP to the server is blocked

When the server or the network does not allow HTTP/3, the client falls back to HTTP/2 or HTTP/1.1. So the same code keeps working behind a corporate firewall. The JDK has no HTTP/3 server, and HTTP/3 works only with the default TLS provider, SunJSSE.

2.3. AOT Cache With ZGC and Other Collectors (JEP 516)

The AOT (ahead-of-time) cache from Java 24 and 25 (JEP 483 and JEP 514) is a file that makes startup faster. A training run records the classes our app loads, and the next start reads them. The cache also stores Java objects, but ZGC could not read their format. JDK 26 adds a format that works with every garbage collector, so ZGC apps start faster too.

java -XX:+UseZGC -XX:AOTCacheOutput=app.aot -cp app.jar com.howtodoinjava.java26.runtime.StartupApp
java -XX:+UseZGC -XX:AOTCache=app.aot -Xlog:aot -cp app.jar com.howtodoinjava.java26.runtime.StartupApp

On JDK 26, the second run logs full module graph: enabled and Using AOT-linked classes: true. The same commands on JDK 25 log disabled and false, because JDK 25 cannot load cached objects with ZGC.

2.4. Faster G1 Write Barriers (JEP 522)

G1 is the default collector. Every time our code stores an object reference in a field, G1 runs a few extra instructions called a write barrier. JDK 26 cuts the write barrier from about 50 instructions to 12 on x64, so apps that change many reference fields get 5 to 15% more throughput. There is nothing to configure, and the cost is about 2 MB of native memory per 1 GB of heap.

3. Preview APIs That Came Back From Java 25

Each preview API in JDK 26 was already a preview in Java 25 and comes back with changes, so Java 25 preview code often needs edits. We compile with javac –release 26 –enable-preview and run with java –enable-preview. The class files load only on JDK 26. The Vector API (JEP 529) is in its eleventh incubator round with no real changes and needs –add-modules jdk.incubator.vector instead.

Table of five preview and incubator APIs showing their JEP numbers in Java 25, Java 26 and Java 27
Each Java 26 preview API was already a preview in Java 25 and comes back again in Java 27, so none of them is final yet.

3.1. LazyConstant Replaces StableValue (JEP 526)

A lazy constant fits a price list that is slow to load and that only some requests need. Its supplier runs once, when code first calls get(), and after that the JVM can treat the value like a final field. Java 26 renames the Java 25 StableValue preview to LazyConstant and drops low-level methods such as trySet(). Lazy collections come from List.ofLazy() and Map.ofLazy().

static final LazyConstant<PriceList> PRICES = LazyConstant.of(PriceList::load);

boolean ready = PRICES.isInitialized();                   // false
int apples = PRICES.get().prices().get("apple");          // 5, PriceList.load() runs once
boolean readyNow = PRICES.isInitialized();                // true
List<Integer> squares = List.ofLazy(5, i -> i * i);
int third = squares.get(3);                               // 9, computed on first access

3.2. Structured Concurrency, Sixth Preview (JEP 525)

With structured concurrency, we start (fork) related subtasks in one StructuredTaskScope, and they finish together. If one subtask fails, the scope cancels the rest. The sixth preview makes small API changes. For example, Joiner.allSuccessfulOrThrow() returns a List of results instead of a stream of subtasks, and anySuccessfulResultOrThrow() is renamed to anySuccessfulOrThrow().

try (var scope = StructuredTaskScope.open(Joiner.<Integer>allSuccessfulOrThrow())) {
    scope.fork(() -> stock("apple"));
    scope.fork(() -> stock("banana"));
    List<Integer> stocks = scope.join();                     // [5, 6]
}

If one subtask throws, join() throws StructuredTaskScope.FailedException with the original exception as the cause.

3.3. Matching int and double Values With Patterns (JEP 530)

Before this preview, pattern matching in instanceof and switch worked only with reference types such as Integer. JEP 530 allows primitive types such as int and double too. A primitive pattern matches only when the value converts without losing information, for example 300 does not fit in a byte. The fourth preview also adds stricter checks on the order of case labels, so a few switch blocks that compiled on Java 25 fail on Java 26.

int count = 300;
String size = switch (count) {
    case byte b -> "fits in a byte: " + b;
    case int i -> "needs an int: " + i;
};                                                           // "needs an int: 300"
double rating = 4.0;
String stars = rating instanceof int whole ? whole + " stars" : rating + " stars";   // "4 stars"

For count = 100, the byte case matches instead, and for rating = 4.5, the instanceof test is false.

3.4. PEM Encodings for Keys and Certificates (JEP 524)

Keys and certificates often come as PEM text. PEM is the Base64 block that OpenSSL writes between lines such as —–BEGIN PUBLIC KEY—–. The PEMEncoder and PEMDecoder classes turn a public key, a private key or a certificate into PEM text and back. In the second preview, PEMRecord is renamed to PEM, and encrypted KeyPair objects are supported.

4. APIs Removed in JDK 26

Removed APIs are the only JDK 26 changes that can break a build, so we search for them before upgrading. JEP 504 removes the Applet API. It was deprecated for removal in JDK 17 and could not run anywhere once JDK 24 disabled the Security Manager.

  • The java.applet package, javax.swing.JApplet and java.beans.AppletInitializer are gone.
  • The method Thread.stop() is removed (JDK-8368226), so we stop a thread by interrupting it and checking the interrupt flag.
  • The jrunscript tool and the jdk.jsobject module are removed.

5. Smaller API Additions Without a JEP

Several final APIs came in through the JDK 26 release notes without a JEP. For example, UUID.ofEpochMillis() creates a time-ordered version 7 UUID, and Comparator gets min() and max() default methods. The Process class also implements Closeable. So a try-with-resources block closes its streams and destroys the process if it is still running.

6. Moving a Maven Project to JDK 26

Java 25 code compiles on Java 26 unchanged unless it uses an API from section 4. We set the Java version in Maven to 26 and add –enable-preview only when we use the preview APIs.

<properties>
  <maven.compiler.release>26</maven.compiler.release>
</properties>

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.16.0</version>
  <configuration>
    <compilerArgs>
      <arg>--enable-preview</arg>
    </compilerArgs>
  </configuration>
</plugin>

The Surefire plugin, which runs our tests, needs the same flag in its argLine. JDK 26 writes class file version 70. A Java 25 runtime rejects that file with UnsupportedClassVersionError, as explained in Unsupported class file major version 69.

7. Conclusion

HTTP/3 support and the AOT cache with ZGC are the Java 26 features we notice first. Every app on G1 also gets faster without a code change. The JEP 500 warning is the change to act on, because a later release turns it into an IllegalAccessException.

The preview APIs changed again and stay in preview. So we keep them in experiments and tests, while production apps stay on Java 25.

8. References

Happy Learning !!

Source Code on Github

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.