Java 26 New Features
Deep dive into Java 26 (JDK 26) new features. Learn about HTTP/3, Lazy Constants, and Structured Concurrency with real-world examples and internal concepts.
"Java 26 marks a turning point in the platform's performance story, bridging the gap between network modernization and internal runtime efficiency."
The release of JDK 26 on March 17, 2026, brought ten JDK Enhancement Proposals (JEPs) that solve long-standing friction points for developers. From the way we initialize expensive objects to how we handle concurrent tasks, Java 26 is about making the language more robust and the runtime faster.
HTTP/3 for the HTTP Client API
JEP 517🔹 Problem
✅ Solution
java.net.http.HttpClient. By using the UDP-based QUIC protocol, it enables independent streams where one lost packet only affects its specific stream, not the entire connection.⚙️ How It Works
Version.HTTP_3, the client uses a QUIC transport. If the server doesn't support it or UDP is blocked by a firewall, it gracefully downgrades to HTTP/2.import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
// 1. Create a client that prefers HTTP/3
try (HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_3)
.build()) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://openjdk.org"))
.GET()
.build();
// 2. The client negotiates QUIC automatically
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
System.out.println("Actual Protocol: " + response.version());
}Lazy Constants (Stable Values)
JEP 526🔹 Problem
static final at initialization time.✅ Solution
java.lang.LazyConstant<T>. It provides a clean API for deferred, one-time initialization that is natively understood by the JVM's JIT compiler.⚙️ How It Works
LazyConstant is computed, the JIT compiler can perform "constant folding." This means it treats the value as if it were a literal constant, potentially inlining it directly into machine code for maximum speed.import java.lang.LazyConstant;
public class AppConfig {
// Defines an uninitialized constant
private static final LazyConstant<DatabaseClient> DB =
LazyConstant.of(() -> new DatabaseClient("prod-url"));
public void start() {
// Initialization happens exactly once on the first .get()
// Subsequent calls are as fast as reading a final field
DB.get().connect();
}
}Structured Concurrency
JEP 525🔹 Problem
ExecutorService) leads to "orphaned threads." If a main task fails, its subtasks often keep running blindly, wasting resources and making debugging a nightmare because stack traces don't show the relationship between parent and child tasks.✅ Solution
StructuredTaskScope (6th Preview). It treats groups of related tasks as a single unit. If the scope closes, all subtasks are guaranteed to be terminated.⚙️ How It Works
onTimeout()callback was added, allowing custom joiners to handle partial results when a time limit is reached, rather than just throwing an exception.import java.util.concurrent.StructuredTaskScope;
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
// Fork subtasks
var userTask = scope.fork(() -> fetchUser(id));
var orderTask = scope.fork(() -> fetchOrders(id));
scope.join(); // Wait for both
scope.throwIfFailed(); // Propagate any error from subtasks
// If one fails, the other is automatically cancelled
return new Dashboard(userTask.get(), orderTask.get());
}Primitive Types in Patterns
JEP 530🔹 Problem
int was actually abyte, you had to manually cast and check ranges, which is error-prone and verbose.✅ Solution
instanceof andswitch patterns. It provides safe, lossless conversion and binding in one step.⚙️ How It Works
public void process(int value) {
// Safe binding: only matches if value fits in a byte
if (value instanceof byte b) {
System.out.println("It's a small number: " + b);
}
// Switch on doubles and floats (new in Java 26!)
double d = 42.0;
switch (d) {
case 0.0 -> System.out.println("Zero");
case double val when val > 0 -> System.out.println("Positive");
default -> System.out.println("Negative");
}
}G1 GC: Contention Reduction
JEP 522🔹 Problem
✅ Solution
⚙️ How It Works
// No code changes needed! Just run on JDK 26 // Throughput gains are automatic for G1 java -XX:+UseG1GC -Xmx16g -jar my-big-app.jar
Other notable removals and additions
- PEM API (JEP 524): Finally, a standard way to read
.pemcertificates without BouncyCastle. - Applet Removal (JEP 504): The
java.appletpackage is officially gone. - AOT for ZGC (JEP 516): Ahead-of-Time object caching now works with the low-latency ZGC.