Java 26 Adds Full HTTP/3 Client Support: Faster, Safer Connections with QUIC
Java 26 introduces HTTP/3 support in its HTTP Client API, enabling developers to use QUIC-based connections with minimal code changes, including three protocol discovery modes and automatic fallback to HTTP/2 or HTTP/1.1 when servers lack HTTP/3 support.
Java 26 updates the HttpClient API to support the HTTP/3 protocol, allowing libraries and applications to interact with HTTP/3 servers with minimal code modifications. The implementation has several limitations: it does not provide a native QUIC protocol API, does not support third-party security socket providers, does not offer a server-side HTTP/3 implementation, and does not update the legacy java.net.URL API which remains limited to HTTP/1.1.
What Is HTTP/3
HTTP/3 replaces the TCP transport layer with QUIC (Quick UDP Internet Connections), delivering significant improvements in performance, reliability, and security. QUIC merges the transport handshake with the TLS 1.3 handshake into a single round trip, reducing connection establishment latency — especially beneficial on high-latency and mobile networks. QUIC streams are independent; packet loss affects only the impacted stream while others continue uninterrupted. Most modern browsers already support HTTP/3 and automatically enable it when servers advertise support.
Practical Examples
2.1 Declaring HTTP/3
To send requests over HTTP/3, you must explicitly enable the protocol. Set the protocol version on the HttpClient so all requests default to HTTP/3:
var client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_3)
.build();You can also set the preferred version on a single HttpRequest:
var request = HttpRequest.newBuilder(URI.create("https://api.pack.com/"))
.version(HttpClient.Version.HTTP_3)
.GET()
.build();No further changes are required. If the target server does not support HTTP/3, the request transparently falls back to HTTP/2 or HTTP/1.1.
2.2 Protocol Discovery
Because HTTP/3 runs over UDP-based QUIC while HTTP/1.1 and HTTP/2 use TCP, the client cannot upgrade an existing connection. The HttpOption.H3_DISCOVERY option controls how the client discovers HTTP/3 support, with three modes:
ANY (default) : The client uses its own algorithm, attempting both QUIC-based HTTP/3 and TLS/TCP-based HTTP, preferring whichever connects first.
HTTP_3_URI_ONLY : The client directly tries HTTP/3 on the host and port from the request URI, without using the Alternative Services mechanism. This succeeds only if the server already listens for HTTP/3 on that port.
ALT_SVC : The client relies solely on HTTP Alternative Services (RFC 7838) to discover HTTP/3. The server responds to an initial HTTP/1.1 or HTTP/2 request with an Alt-Svc header (or HTTP/2 ALTSVC frame) advertising an h3 endpoint; subsequent requests then use HTTP/3.
Example using HTTP_3_URI_ONLY to connect directly without waiting for Alt-Svc advertisement:
public HttpResponse<String> fetch(String url) throws Exception {
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_3)
.build();
HttpRequest request = HttpRequest.newBuilder(URI.create(url)).GET()
.setOption(HttpOption.H3_DISCOVERY, HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY)
.build();
return client.send(request, BodyHandlers.ofString());
}2.3 Verifying a Valid HTTP/3 Endpoint
The article tests against https://cloudflare-quic.com/, a public Cloudflare endpoint for HTTP/3 experimentation. The complete runnable example:
public static void main(String[] args) {
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_3)
.build();
HttpResponse<String> response = null;
try {
response = fetch("https://cloudflare-quic.com/");
} catch (Exception e) {
e.printStackTrace();
}
System.err.println(response.statusCode() + "@" + response.version());
}
public static HttpResponse<String> fetch(String url) throws Exception {
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_3)
.build();
HttpRequest request = HttpRequest.newBuilder(URI.create(url)).GET()
.setOption(HttpOption.H3_DISCOVERY, HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY).build();
return client.send(request, BodyHandlers.ofString());
}Output confirms successful HTTP/3 communication:
200@HTTP_3Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
