JDK 26 新特性详解

JDK 26 新特性详解

JDK 26 于 2026 年 3 月发布,是 JDK 25(LTS)之后的第一个非 LTS 版本。

本版本共有 10 个 JEP,其中 5 个正式特性、4 个预览特性、1 个孵化特性。

JDK 26 在并发、网络、性能和安全方面均有重要改进。


目录

  1. [HTTP/3 Client HTTP/3 客户端](#HTTP/3 Client HTTP/3 客户端)
  2. [AOT Object Caching AOT 对象缓存](#AOT Object Caching AOT 对象缓存)
  3. [G1 GC Throughput Improvement G1 吞吐量提升](#G1 GC Throughput Improvement G1 吞吐量提升)
  4. [Final Field Integrity 终态字段完整性](#Final Field Integrity 终态字段完整性)
  5. [Remove Applet API 移除 Applet API](#Remove Applet API 移除 Applet API)
  6. [Structured Concurrency 结构化并发(第六次预览)](#Structured Concurrency 结构化并发(第六次预览))
  7. [Primitive Types in Patterns 原始类型模式(第四次预览)](#Primitive Types in Patterns 原始类型模式(第四次预览))
  8. [PEM Encoding API PEM 编码 API(第二次预览)](#PEM Encoding API PEM 编码 API(第二次预览))
  9. [Lazy Constants 延迟常量(第二次预览)](#Lazy Constants 延迟常量(第二次预览))
  10. [Vector API 向量 API(第十一次孵化)](#Vector API 向量 API(第十一次孵化))
  11. [JDK 26 特性总览表](#JDK 26 特性总览表)

1. HTTP/3 Client HTTP/3 客户端

1.1 概述

JEP 517 --- HTTP/3 Client(HTTP/3 客户端)。JDK 26 为 java.net.http.HttpClient 添加了 HTTP/3 协议支持,基于 QUIC 传输协议。

改进

  • 原生支持 HTTP/3 协议(基于 QUIC/UDP)
  • 0-RTT 连接建立,大幅降低延迟
  • 多路复用无队头阻塞
  • 连接迁移(网络切换不断连)
  • 与现有 HttpClient API 完全兼容
  • 自动协商(HTTP/3 → HTTP/2 → HTTP/1.1 回退)

1.2 使用方式

java 复制代码
import java.net.http.*;
import java.net.URI;
import java.time.Duration;

// ============ 1. 基本 HTTP/3 请求 ============

// 创建支持 HTTP/3 的客户端
HttpClient client = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_3)  // 优先使用 HTTP/3
    .connectTimeout(Duration.ofSeconds(10))
    .build();

// 发送 GET 请求
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/data"))
    .GET()
    .build();

HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());

System.out.println("Status: " + response.statusCode());
System.out.println("Version: " + response.version());  // HTTP_3
System.out.println("Body: " + response.body());

// ============ 2. 异步 HTTP/3 请求 ============

HttpClient asyncClient = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_3)
    .build();

asyncClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
    .thenApply(HttpResponse::body)
    .thenAccept(body -> System.out.println("Async response: " + body))
    .join();

// ============ 3. 协议版本回退 ============

// 设置 HTTP/3 优先,服务器不支持时自动回退
HttpClient fallbackClient = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_3)  // 优先 HTTP/3
    // 如果服务器不支持 HTTP/3,自动回退到 HTTP/2 或 HTTP/1.1
    .build();

HttpResponse<String> resp = fallbackClient.send(request,
    HttpResponse.BodyHandlers.ofString());

// 检查实际使用的协议版本
System.out.println("Actual version: " + resp.version());
// 可能输出: HTTP_3, HTTP_2, 或 HTTP_1_1

// ============ 4. POST 请求 ============

String jsonBody = """
    {"name": "Alice", "age": 30}
    """;

HttpRequest postRequest = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
    .build();

HttpResponse<String> postResp = client.send(postRequest,
    HttpResponse.BodyHandlers.ofString());
System.out.println("Created: " + postResp.statusCode());  // 201

// ============ 5. 并发请求(HTTP/3 多路复用优势)============

// HTTP/3 的多路复用无队头阻塞,并发性能更优
List<URI> uris = List.of(
    URI.create("https://api.example.com/users/1"),
    URI.create("https://api.example.com/users/2"),
    URI.create("https://api.example.com/users/3"),
    URI.create("https://api.example.com/users/4"),
    URI.create("https://api.example.com/users/5")
);

// 所有请求在单个 QUIC 连接上多路复用
List<CompletableFuture<HttpResponse<String>>> futures = uris.stream()
    .map(uri -> HttpRequest.newBuilder(uri).GET().build())
    .map(req -> asyncClient.sendAsync(req, HttpResponse.BodyHandlers.ofString()))
    .toList();

// 等待所有响应
List<String> bodies = futures.stream()
    .map(CompletableFuture::join)
    .map(HttpResponse::body)
    .toList();

// ============ 6. 流式响应(大文件下载)============

HttpRequest downloadReq = HttpRequest.newBuilder()
    .uri(URI.create("https://cdn.example.com/large-file.zip"))
    .GET()
    .build();

HttpResponse<InputStream> streamResp = client.send(downloadReq,
    HttpResponse.BodyHandlers.ofInputStream());

try (InputStream is = streamResp.body();
     OutputStream os = Files.newOutputStream(Path.of("download.zip"))) {
    is.transferTo(os);
}

// ============ 7. 配置超时和重试 ============

HttpClient robustClient = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_3)
    .connectTimeout(Duration.ofSeconds(5))
    .followRedirects(HttpClient.Redirect.NORMAL)
    .build();

HttpRequest timedReq = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/slow"))
    .timeout(Duration.ofSeconds(30))  // 请求级超时
    .GET()
    .build();

// ============ 8. HTTP/3 vs HTTP/2 对比 ============

// | 特性 | HTTP/2 | HTTP/3 |
// |------|--------|--------|
// | 传输层 | TCP | QUIC (UDP) |
// | 队头阻塞 | 有(TCP 层)| 无 |
// | 连接建立 | 1-2 RTT | 0-1 RTT |
// | 连接迁移 | 不支持 | 支持 |
// | 加密 | 可选 TLS | 强制 TLS 1.3 |
// | 多路复用 | 有(受 TCP 限制)| 有(无限制)|

// ============ 9. 与虚拟线程配合 ============

// HTTP/3 + 虚拟线程 = 超高并发网络客户端
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    List<Future<String>> results = new ArrayList<>();

    for (int i = 0; i < 10_000; i++) {
        final int id = i;
        results.add(executor.submit(() -> {
            HttpRequest req = HttpRequest.newBuilder()
                .uri(URI.create("https://api.example.com/items/" + id))
                .GET()
                .build();
            return client.send(req, HttpResponse.BodyHandlers.ofString()).body();
        }));
    }

    // 处理结果...
}

2. AOT Object Caching AOT 对象缓存

2.1 概述

JEP 516 --- AOT Object Caching(AOT 对象缓存)。JDK 26 扩展了 JDK 24 引入的 AOT 机制,支持缓存对象(不仅是类),并兼容所有 GC。

改进

  • 缓存应用启动时创建的对象(如配置、元数据)
  • 支持所有垃圾收集器(G1、ZGC、Shenandoah、Parallel)
  • 进一步缩短启动时间
  • 减少启动阶段的内存分配和 GC 压力

2.2 使用方式

bash 复制代码
# ============ 1. 创建 AOT 缓存(训练运行)============

# 第一次运行:记录类加载和对象创建信息
java -XX:AOTMode=record -XX:AOTCache=app.aot -jar app.jar

# 应用正常运行,同时生成缓存文件

# ============ 2. 使用 AOT 缓存启动 ============

# 后续运行:从缓存恢复,跳过大量初始化
java -XX:AOTCache=app.aot -jar app.jar

# ============ 3. 与不同 GC 配合使用 ============

# G1 GC(默认)
java -XX:AOTCache=app.aot -jar app.jar

# ZGC
java -XX:+UseZGC -XX:AOTCache=app.aot -jar app.jar

# Shenandoah
java -XX:+UseShenandoahGC -XX:AOTCache=app.aot -jar app.jar

# Parallel GC
java -XX:+UseParallelGC -XX:AOTCache=app.aot -jar app.jar

# ============ 4. JDK 24 vs JDK 26 AOT 对比 ============

# JDK 24(JEP 483):
# - 只缓存类加载和链接信息
# - 只支持默认 GC 配置

# JDK 26(JEP 516):
# - 缓存类加载 + 对象实例
# - 支持所有 GC
# - 启动加速效果更显著

# ============ 5. 启动时间对比(典型 Spring Boot 应用)============

# 无优化:~3.5 秒
# CDS(JDK 13+):~2.8 秒
# AOT 类加载(JDK 24):~1.5 秒
# AOT 对象缓存(JDK 26):~0.8 秒

# ============ 6. 容器化部署 ============

# Dockerfile
FROM eclipse-temurin:26-jdk AS builder
COPY app.jar /app/app.jar
# 训练运行生成缓存
RUN java -XX:AOTMode=record -XX:AOTCache=/app/app.aot -jar /app/app.jar --init-only

FROM eclipse-temurin:26-jre
COPY --from=builder /app/app.jar /app/app.jar
COPY --from=builder /app/app.aot /app/app.aot
ENTRYPOINT ["java", "-XX:AOTCache=/app/app.aot", "-jar", "/app/app.jar"]

# ============ 7. 注意事项 ============

# - AOT 缓存与 JDK 版本绑定
# - 缓存文件包含应用状态信息(注意安全)
# - 动态生成的类/对象可能无法缓存
# - 缓存文件大小取决于应用复杂度
# - 建议在 CI/CD 中生成缓存

3. G1 GC Throughput Improvement G1 吞吐量提升

3.1 概述

JEP 522 --- G1 GC Throughput Improvement(G1 GC 吞吐量提升)。JDK 26 通过减少同步开销(双卡表机制)显著提升了 G1 GC 的吞吐量。

改进

  • 引入双卡表(Dual Card Table)机制
  • 减少 GC 屏障的同步开销
  • 提升多线程应用的 GC 吞吐量
  • 对高并发应用效果尤为显著
  • 无需任何配置,升级即生效

3.2 使用方式

bash 复制代码
# ============ 1. 默认启用(无需配置)============

# JDK 26 中 G1 GC 自动使用优化后的实现
java -jar app.jar

# 显式指定 G1(默认就是 G1)
java -XX:+UseG1GC -jar app.jar

# ============ 2. 监控 G1 性能 ============

# GC 日志
java -XX:+UseG1GC -Xlog:gc*:file=gc.log:time,level,tags -jar app.jar

# 查看 GC 统计
java -XX:+UseG1GC -Xlog:gc+stats=info -jar app.jar

# ============ 3. 性能对比 ============

# JDK 25 G1 vs JDK 26 G1(高并发场景):
# - 吞吐量提升:5%-15%
# - GC 暂停时间:基本不变
# - 内存占用:基本不变
# - CPU 利用率:更高效

# ============ 4. 适用场景 ============

# 受益最大的场景:
# - 高并发 Web 服务(大量虚拟线程/平台线程)
# - 写密集型应用(频繁对象创建)
# - 大堆应用(> 8GB)
# - 多线程数据处理管道

# ============ 5. G1 常用调优参数(JDK 26)============

# 目标暂停时间
java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar app.jar

# 堆大小
java -XX:+UseG1GC -Xms4g -Xmx4g -jar app.jar

# 区域大小
java -XX:+UseG1GC -XX:G1HeapRegionSize=16m -jar app.jar

# 混合 GC 触发阈值
java -XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=45 -jar app.jar

4. Final Field Integrity 终态字段完整性

4.1 概述

JEP 500 --- Final Field Integrity(终态字段完整性)。JDK 26 加强了 final 字段的不可变性保证,通过反射修改 final 字段时会产生警告。

改进

  • 通过反射修改 final 字段时产生运行时警告
  • 为未来完全禁止反射修改 final 字段做准备
  • 提升代码安全性和可预测性
  • 帮助发现潜在的并发安全问题

4.2 使用方式

java 复制代码
import java.lang.reflect.Field;

// ============ 1. 问题背景 ============

class Config {
    final String env = "production";
    final int maxRetries = 3;
}

// JDK 25 及之前:可以通过反射修改 final 字段(危险!)
Config cfg = new Config();
Field f = Config.class.getDeclaredField("env");
f.setAccessible(true);
f.set(cfg, "development");  // JDK 25: 静默成功
System.out.println(cfg.env);  // "development" --- 破坏了不可变性!

// ============ 2. JDK 26 行为变化 ============

// JDK 26:反射修改 final 字段会产生警告
Config cfg2 = new Config();
Field f2 = Config.class.getDeclaredField("env");
f2.setAccessible(true);
f2.set(cfg2, "staging");
// 控制台输出警告:
// WARNING: Illegal reflective access to final field 'env' in class Config
// WARNING: This operation will be disallowed in a future release

System.out.println(cfg2.env);  // 行为可能不确定

// ============ 3. 正确的替代方案 ============

// 方案一:使用不可变设计(推荐)
record AppConfig(String env, int maxRetries) {}

AppConfig config = new AppConfig("production", 3);
// config.env() 永远不可变

// 方案二:使用 setter(如果确实需要可变)
class MutableConfig {
    private String env = "production";

    public String getEnv() { return env; }
    public void setEnv(String env) { this.env = env; }
}

// 方案三:使用 AtomicReference(并发安全的可变)
class ConcurrentConfig {
    private final AtomicReference<String> env =
        new AtomicReference<>("production");

    public String getEnv() { return env.get(); }
    public void setEnv(String newEnv) { env.set(newEnv); }
}

// ============ 4. 框架迁移指南 ============

// 许多序列化/反序列化框架依赖反射修改 final 字段
// JDK 26 中这些框架需要更新:

// 旧方式(框架内部):
// Field field = obj.getClass().getDeclaredField("id");
// field.setAccessible(true);
// field.set(obj, deserializedValue);  // JDK 26 产生警告

// 新方式(框架应使用):
// 1. 使用构造器注入(推荐)
// 2. 使用 VarHandle
// 3. 使用 MethodHandle
// 4. 使用 Unsafe(临时方案,最终也会被限制)

// ============ 5. 检测项目中的问题代码 ============

// 运行时添加参数检测所有反射修改 final 字段的位置:
// java -Djava.lang.reflect.finalField.warning=verbose -jar app.jar

// 编译时检查:
// javac -Xlint:all MyClass.java

// ============ 6. 时间线 ============

// JDK 26:反射修改 final 字段 → 产生警告
// 未来版本:反射修改 final 字段 → 抛出异常
// 建议:尽早迁移,不要依赖反射修改 final 字段

5. Remove Applet API 移除 Applet API

5.1 概述

JEP 504 --- Remove the Applet API(移除 Applet API)。JDK 26 彻底移除了 java.applet 包中的所有类。

改进

  • 移除 java.applet.Applet
  • 移除 java.applet.AppletContext 等接口
  • 清理历史遗留代码
  • Applet 在 JDK 17 中已标记为弃用(for removal)

5.2 使用方式

java 复制代码
// ============ 1. 已移除的类 ============

// 以下类在 JDK 26 中不再存在:
// - java.applet.Applet
// - java.applet.AppletContext
// - java.applet.AppletStub
// - java.applet.AudioClip

// 编译使用这些类的代码会报错:
// error: package java.applet does not exist

// ============ 2. 迁移方案 ============

// 如果有遗留 Applet 代码,迁移选择:

// 方案一:迁移到 Java Web Start(也已弃用)→ 桌面应用
// 方案二:迁移到 JavaFX 富客户端
// 方案三:迁移到 Web 技术(HTML5 + JavaScript)
// 方案四:迁移到服务端渲染 + REST API

// ============ 3. 检查依赖 ============

// 检查项目是否依赖 Applet API:
// grep -r "java.applet" src/
// grep -r "extends Applet" src/
// grep -r "import java.applet" src/

// 大多数现代项目不会受影响
// Applet 技术已被淘汰超过 10 年

6. Structured Concurrency 结构化并发(第六次预览)

6.1 概述

JEP 525 --- Structured Concurrency(结构化并发,第六次预览)。JDK 26 为结构化并发添加了超时支持(Joiner 超时),进一步简化并发编程。

改进

  • 新增 Joiner.onTimeout() --- 超时后返回默认值
  • 新增 Joiner.anySuccessfulOrThrow() 超时变体
  • 更灵活的子任务生命周期管理
  • 经过 6 次预览迭代,API 趋于稳定

6.2 使用方式

java 复制代码
import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.StructuredTaskScope.Joiner;
import java.util.concurrent.StructuredTaskScope.Subtask;

// ============ 1. 基本并行聚合(与之前版本相同)============

record UserProfile(User user, List<Order> orders) {}

UserProfile fetchProfile(String userId) throws Exception {
    try (var scope = StructuredTaskScope.open(
            Joiner.<Object>allSuccessfulOrThrow())) {

        Subtask<User> user = scope.fork(() -> getUser(userId));
        Subtask<List<Order>> orders = scope.fork(() -> getOrders(userId));

        scope.join();

        return new UserProfile(user.get(), orders.get());
    }
}

// ============ 2. 新增:超时 Joiner ============

// 超时后返回默认值,而非抛异常
Response handleWithTimeout(String requestId) throws Exception {
    try (var scope = StructuredTaskScope.open(
            Joiner.anySuccessfulOrThrow(),
            builder -> builder.withTimeout(Duration.ofMillis(300)))) {

        scope.fork(() -> callPrimaryService(requestId));
        scope.fork(() -> callSecondaryService(requestId));

        scope.join();

        return scope.result();
    } catch (TimeoutException e) {
        return Response.fallback();  // 超时返回默认响应
    }
}

// ============ 3. 超时 + 默认值 Joiner ============

String fetchWithFallback(String url) throws Exception {
    try (var scope = StructuredTaskScope.open(
            Joiner.onTimeout(Duration.ofSeconds(2), () -> "cached-default"))) {

        scope.fork(() -> httpGet(url));
        scope.fork(() -> httpGetMirror(url));

        scope.join();

        return scope.result();  // 超时则返回 "cached-default"
    }
}

// ============ 4. 竞速模式(取最快结果)============

<T> T race(List<Callable<T>> tasks) throws Exception {
    try (var scope = StructuredTaskScope.open(
            Joiner.<T>anySuccessfulOrThrow())) {

        tasks.forEach(scope::fork);
        scope.join();

        return scope.result();
    }
}

// 使用:从多个 CDN 取最快的
String content = race(List.of(
    () -> fetchFromCDN1(path),
    () -> fetchFromCDN2(path),
    () -> fetchFromCDN3(path)
));

// ============ 5. 批量处理 + 超时 ============

List<Result> processBatch(List<Task> tasks) throws Exception {
    try (var scope = StructuredTaskScope.open(
            Joiner.allSuccessfulOrThrow(),
            builder -> builder.withTimeout(Duration.ofSeconds(30)))) {

        List<Subtask<Result>> subtasks = tasks.stream()
            .map(t -> scope.fork(() -> execute(t)))
            .toList();

        scope.join();

        return subtasks.stream()
            .map(Subtask::get)
            .toList();
    }
}

// ============ 6. 与虚拟线程配合 ============

// StructuredTaskScope 内部自动使用虚拟线程
// 可以轻松 fork 大量子任务
try (var scope = StructuredTaskScope.open(
        Joiner.allSuccessfulOrThrow())) {

    for (int i = 0; i < 10_000; i++) {
        final int id = i;
        scope.fork(() -> processItem(id));
    }

    scope.join();
}

// ============ 7. 错误处理策略 ============

// 策略一:全部成功或抛异常
Joiner.allSuccessfulOrThrow()

// 策略二:任一成功即返回
Joiner.anySuccessfulOrThrow()

// 策略三:超时返回默认值
Joiner.onTimeout(Duration.ofSeconds(5), () -> defaultValue)

// 策略四:自定义 Joiner
Joiner<Object> custom = Joiner.of(completedSubtasks -> {
    // 自定义完成逻辑
    return completedSubtasks.stream()
        .filter(s -> s.state() == Subtask.State.SUCCESS)
        .map(Subtask::get)
        .toList();
});

7. Primitive Types in Patterns 原始类型模式(第四次预览)

7.1 概述

JEP 530 --- Primitive Types in Patterns(原始类型模式,第四次预览)。JDK 26 继续改进原始类型在模式匹配中的支持,接近最终定稿。

改进

  • 经过 JDK 23(预览)→ JDK 24(第二次预览)→ JDK 25(第三次预览)→ JDK 26(第四次预览)
  • instanceofswitch 全面支持所有原始类型
  • 安全的窄化转换匹配
  • API 趋于稳定

7.2 使用方式

java 复制代码
// ============ 1. switch 匹配所有原始类型 ============

String format(Object value) {
    return switch (value) {
        case byte b -> "0x" + Integer.toHexString(b & 0xFF);
        case short s -> "short:" + s;
        case int i -> "int:" + i;
        case long l -> "long:" + l;
        case float f -> String.format("%.2f", f);
        case double d -> String.format("%.4f", d);
        case char c -> "'" + c + "'";
        case boolean b -> b ? "YES" : "NO";
        case String s -> "\"" + s + "\"";
        default -> "unknown";
    };
}

// ============ 2. 带守卫的模式 ============

String classifyPrice(Object price) {
    return switch (price) {
        case int p when p < 100 -> "BUDGET";
        case int p when p < 500 -> "MID-RANGE";
        case int p -> "PREMIUM";
        case double d when d < 100.0 -> "BUDGET";
        case double d -> "PREMIUM";
        default -> "UNKNOWN";
    };
}

// ============ 3. 与 Record Patterns 配合 ============

record SensorReading(String sensor, Object value, long timestamp) {}

void processReading(SensorReading reading) {
    switch (reading) {
        case SensorReading("temperature", double d, _) ->
            System.out.printf("Temp: %.1f°C%n", d);
        case SensorReading("pressure", int p, _) ->
            System.out.printf("Pressure: %d hPa%n", p);
        case SensorReading("active", boolean b, _) ->
            System.out.println("Active: " + b);
        default ->
            System.out.println("Unknown reading: " + reading.sensor());
    }
}

// ============ 4. 数值解析与分发 ============

void handleInput(Object input) {
    switch (input) {
        case int i -> handleInteger(i);
        case long l -> handleLong(l);
        case double d -> handleDouble(d);
        case boolean b -> handleBoolean(b);
        case char c -> handleChar(c);
        case String s -> handleString(s);
        case null -> handleNull();
        default -> handleUnknown(input);
    }
}

// ============ 5. 安全窄化 ============

void narrowDemo(Object obj) {
    switch (obj) {
        // long 值如果在 int 范围内,可以匹配 int 模式
        case int i -> System.out.println("int: " + i);
        case long l -> System.out.println("long only: " + l);
        default -> System.out.println("not a number");
    }
}

narrowDemo(42);            // int: 42
narrowDemo(42L);           // int: 42(在 int 范围内)
narrowDemo(5_000_000_000L); // long only: 5000000000

8. PEM Encoding API PEM 编码 API(第二次预览)

8.1 概述

JEP 524 --- PEM Encoding of Cryptographic Objects(PEM 编码 API,第二次预览)。JDK 26 继续改进 PEM 编码/解码 API,支持将密码学对象与 PEM 格式互相转换。

改进

  • 标准 API 进行 PEM 编码/解码
  • 支持公钥、私钥、证书等密码学对象
  • 替代手动 Base64 + 头尾标记的繁琐操作
  • 与现有 JCA 体系无缝集成

8.2 使用方式

java 复制代码
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;

// ============ 1. 公钥编码为 PEM ============

// 生成 RSA 密钥对
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair keyPair = kpg.generateKeyPair();

// 编码公钥为 PEM 字符串
PEMEncoder encoder = PEMEncoder.of();
String publicKeyPEM = encoder.encodeToString(keyPair.getPublic());
System.out.println(publicKeyPEM);
// -----BEGIN PUBLIC KEY-----
// MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
// -----END PUBLIC KEY-----

// ============ 2. 私钥编码为 PEM ============

String privateKeyPEM = encoder.encodeToString(keyPair.getPrivate());
System.out.println(privateKeyPEM);
// -----BEGIN PRIVATE KEY-----
// MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAo...
// -----END PRIVATE KEY-----

// ============ 3. 从 PEM 解码为密钥对象 ============

PEMDecoder decoder = PEMDecoder.of();

// 解码公钥
PublicKey restoredPublic = decoder.decode(publicKeyPEM);
System.out.println("Algorithm: " + restoredPublic.getAlgorithm());  // RSA

// 解码私钥
PrivateKey restoredPrivate = decoder.decode(privateKeyPEM);

// ============ 4. 从文件读取 PEM ============

// 读取 PEM 文件
String pemContent = Files.readString(Path.of("server.crt"));
PublicKey certKey = decoder.decode(pemContent);

// 读取私钥文件
String keyContent = Files.readString(Path.of("server.key"));
PrivateKey serverKey = decoder.decode(keyContent);

// ============ 5. 写入 PEM 文件 ============

// 保存公钥
Files.writeString(Path.of("public.pem"),
    encoder.encodeToString(keyPair.getPublic()));

// 保存私钥
Files.writeString(Path.of("private.pem"),
    encoder.encodeToString(keyPair.getPrivate()));

// ============ 6. EC 密钥的 PEM 编码 ============

KeyPairGenerator ecKpg = KeyPairGenerator.getInstance("EC");
ecKpg.initialize(new ECGenParameterSpec("secp256r1"));
KeyPair ecKeyPair = ecKpg.generateKeyPair();

String ecPublicPEM = encoder.encodeToString(ecKeyPair.getPublic());
String ecPrivatePEM = encoder.encodeToString(ecKeyPair.getPrivate());

// ============ 7. ML-KEM / ML-DSA 密钥的 PEM 编码 ============

// 抗量子密钥也可以编码为 PEM
KeyPairGenerator mlKpg = KeyPairGenerator.getInstance("ML-KEM");
mlKpg.initialize(new NamedParameterSpec("ML-KEM-768"));
KeyPair mlKeyPair = mlKpg.generateKeyPair();

String mlPublicPEM = encoder.encodeToString(mlKeyPair.getPublic());
String mlPrivatePEM = encoder.encodeToString(mlKeyPair.getPrivate());

// ============ 8. 证书 PEM 编码 ============

// X.509 证书编码
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(
    Files.newInputStream(Path.of("ca.crt")));

String certPEM = encoder.encodeToString(cert);
// -----BEGIN CERTIFICATE-----
// MIIC...
// -----END CERTIFICATE-----

// ============ 9. 实际应用场景 --- TLS 证书配置 ============

// 从 PEM 文件加载 TLS 证书和私钥
String certPem = Files.readString(Path.of("tls/server.crt"));
String keyPem = Files.readString(Path.of("tls/server.key"));

PublicKey tlsPublic = decoder.decode(certPem);
PrivateKey tlsPrivate = decoder.decode(keyPem);

// 用于配置 SSLContext
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null, null);
ks.setKeyEntry("server", tlsPrivate, "changeit".toCharArray(),
    new java.security.cert.Certificate[]{(java.security.cert.Certificate) decoder.decode(certPem)});

// ============ 10. 与手动 Base64 方式对比 ============

// 传统手动方式(繁琐且易错):
String manualPem = "-----BEGIN PUBLIC KEY-----\n" +
    Base64.getMimeEncoder(64, "\n".getBytes())
        .encodeToString(keyPair.getPublic().getEncoded()) +
    "\n-----END PUBLIC KEY-----\n";

// JDK 26 PEM API(简洁安全):
String apiPem = PEMEncoder.of().encodeToString(keyPair.getPublic());

9. Lazy Constants 延迟常量(第二次预览)

9.1 概述

JEP 526 --- Lazy Constants(延迟常量,第二次预览)。JDK 26 引入 LazyConstant API,提供线程安全的延迟初始化机制,替代 static final 急切初始化和双重检查锁定模式。

改进

  • 线程安全的延迟初始化(无需 synchronized)
  • 值只计算一次,后续访问零开销
  • 替代双重检查锁定(DCL)反模式
  • 替代 static final 急切初始化(加速启动)
  • JVM 可以内联优化,性能等同直接字段访问

9.2 使用方式

java 复制代码
import java.lang.LazyConstant;

// ============ 1. 基本用法 ============

// 延迟初始化一个昂贵的对象
private final LazyConstant<DatabaseConnection> dbConnection =
    LazyConstant.of(() -> DatabaseConnection.create("jdbc:mysql://localhost/app"));

// 第一次访问时初始化
void query() {
    DatabaseConnection conn = dbConnection.get();  // 首次调用触发初始化
    conn.execute("SELECT ...");
}

// 后续访问直接返回缓存值(零开销)
void anotherQuery() {
    DatabaseConnection conn = dbConnection.get();  // 直接返回,无同步开销
    conn.execute("SELECT ...");
}

// ============ 2. 替代 static final 急切初始化 ============

// 传统方式:类加载时就初始化(拖慢启动)
class AppContext {
    // 即使不使用也会初始化
    private static final Logger LOGGER = Logger.create(AppContext.class);
    private static final Config CONFIG = Config.load();
    private static final MetricsRegistry METRICS = new MetricsRegistry();
}

// JDK 26 方式:按需初始化(加速启动)
class AppContext {
    private static final LazyConstant<Logger> LOGGER =
        LazyConstant.of(() -> Logger.create(AppContext.class));
    private static final LazyConstant<Config> CONFIG =
        LazyConstant.of(() -> Config.load());
    private static final LazyConstant<MetricsRegistry> METRICS =
        LazyConstant.of(() -> new MetricsRegistry());

    void handleRequest() {
        // 只有实际使用时才初始化
        LOGGER.get().info("Processing request");
        Config cfg = CONFIG.get();
    }
}

// ============ 3. 替代双重检查锁定(DCL)============

// 传统 DCL 模式(复杂且易错)
class Singleton {
    private static volatile Singleton instance;

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

// JDK 26 LazyConstant(简洁安全)
class Singleton {
    private static final LazyConstant<Singleton> INSTANCE =
        LazyConstant.of(Singleton::new);

    public static Singleton getInstance() {
        return INSTANCE.get();
    }
}

// ============ 4. 替代 Holder 模式 ============

// 传统 Holder 模式
class ExpensiveService {
    private static class Holder {
        static final ExpensiveService INSTANCE = new ExpensiveService();
    }
    public static ExpensiveService getInstance() {
        return Holder.INSTANCE;
    }
}

// JDK 26 LazyConstant
class ExpensiveService {
    private static final LazyConstant<ExpensiveService> INSTANCE =
        LazyConstant.of(ExpensiveService::new);

    public static ExpensiveService getInstance() {
        return INSTANCE.get();
    }
}

// ============ 5. 实例级延迟初始化 ============

class OrderController {
    // 每个实例独立延迟初始化
    private final LazyConstant<Logger> logger =
        LazyConstant.of(() -> Logger.create(OrderController.class));
    private final LazyConstant<OrderValidator> validator =
        LazyConstant.of(() -> new OrderValidator(loadRules()));

    void handleOrder(Order order) {
        logger.get().debug("Processing order: " + order.id());
        validator.get().validate(order);
    }
}

// ============ 6. 条件性初始化 ============

class FeatureFlags {
    private final LazyConstant<Map<String, Boolean>> flags =
        LazyConstant.of(() -> {
            // 只在第一次访问时从远程加载
            return remoteConfigService.fetchFlags();
        });

    boolean isEnabled(String feature) {
        return flags.get().getOrDefault(feature, false);
    }
}

// ============ 7. 与虚拟线程配合 ============

// LazyConstant 在虚拟线程环境中同样安全高效
class RequestHandler {
    private final LazyConstant<HeavyResource> resource =
        LazyConstant.of(() -> HeavyResource.initialize());

    void handle() {
        // 多个虚拟线程并发调用 get()
        // 只有一个线程执行初始化,其他等待
        HeavyResource r = resource.get();
        r.process();
    }
}

// ============ 8. 性能特点 ============

// | 方式 | 线程安全 | 初始化后开销 | 代码复杂度 |
// |------|----------|-------------|-----------|
// | static final | 是 | 零 | 低 |
// | synchronized | 是 | 每次加锁 | 中 |
// | DCL | 是 | volatile 读 | 高 |
// | Holder | 是 | 零 | 中 |
// | LazyConstant | 是 | 零(JVM 内联)| 低 |

// LazyConstant 的优势:
// - 延迟初始化(不拖慢启动)
// - 初始化后零开销(JVM 可内联)
// - 代码简洁(一行声明)
// - 线程安全(无需手动同步)

// ============ 9. 注意事项 ============

// - LazyConstant 是不可变的(一旦设置不能更改)
// - 初始化函数不应有副作用(或确保幂等)
// - 如果初始化抛异常,后续 get() 会重新尝试
// - 不适合需要重新初始化的场景(用 AtomicReference)
// - 编译运行需要启用预览:
//   javac --enable-preview --source 26 App.java
//   java --enable-preview App

10. Vector API 向量 API(第十一次孵化)

10.1 概述

JEP 529 --- Vector API(向量 API,第十一次孵化)。JDK 26 继续孵化向量 API,等待 Project Valhalla 值类型支持后正式标准化。

10.2 使用方式

java 复制代码
import jdk.incubator.vector.*;

static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_256;

// 向量加法
void add(float[] a, float[] b, float[] c) {
    int i = 0;
    for (; i < SPECIES.loopBound(a.length); i += SPECIES.length()) {
        FloatVector va = FloatVector.fromArray(SPECIES, a, i);
        FloatVector vb = FloatVector.fromArray(SPECIES, b, i);
        va.add(vb).intoArray(c, i);
    }
    for (; i < a.length; i++) c[i] = a[i] + b[i];
}

// 点积
float dot(float[] a, float[] b) {
    FloatVector sum = FloatVector.zero(SPECIES);
    int i = 0;
    for (; i < SPECIES.loopBound(a.length); i += SPECIES.length()) {
        sum = FloatVector.fromArray(SPECIES, a, i)
            .fma(FloatVector.fromArray(SPECIES, b, i), sum);
    }
    float r = sum.reduceLanes(VectorOperators.ADD);
    for (; i < a.length; i++) r += a[i] * b[i];
    return r;
}

// 编译: javac --add-modules jdk.incubator.vector VecDemo.java
// 运行: java --add-modules jdk.incubator.vector VecDemo

11. JDK 26 特性总览表

序号 特性 JEP 类型 状态 重要性
1 HTTP/3 Client JEP 517 网络 正式 ★★★★★
2 AOT Object Caching JEP 516 性能 正式 ★★★★★
3 G1 GC Throughput Improvement JEP 522 GC 正式 ★★★★☆
4 Final Field Integrity JEP 500 安全 正式 ★★★★☆
5 Remove Applet API JEP 504 清理 正式 ★★☆☆☆
6 Structured Concurrency(超时 Joiner) JEP 525 并发 第六次预览 ★★★★★
7 Primitive Types in Patterns JEP 530 语言 第四次预览 ★★★★★
8 PEM Encoding API JEP 524 安全 第二次预览 ★★★★☆
9 Lazy Constants JEP 526 API 第二次预览 ★★★★★
10 Vector API JEP 529 API 第十一次孵化 ★★★☆☆

附录:预览特性状态追踪

特性 JDK 23 JDK 24 JDK 25 JDK 26
Structured Concurrency 第三次预览 第四次预览 第五次预览 第六次预览
Primitive Types in Patterns 预览 第二次预览 第三次预览 第四次预览
PEM Encoding API --- --- 预览 第二次预览
Lazy Constants (Stable Values) --- --- 预览 第二次预览
Vector API 第八次孵化 第九次孵化 第十次孵化 第十一次孵化
Stream Gatherers 第二次预览 正式 --- ---
Class-File API 第二次预览 正式 --- ---
Scoped Values 第三次预览 第四次预览 正式 ---
Module Import Declarations 预览 第二次预览 正式 ---
Simple Source Files 第三次预览 第四次预览 正式 ---
Flexible Constructor Bodies 第二次预览 第三次预览 正式 ---
KDF API --- 预览 正式 ---

附录:JDK 26 与其他版本的关系

项目 说明
发布日期 2026年3月
版本类型 非 LTS(短期支持)
前一个版本 JDK 25(LTS,2025年9月)
下一个版本 JDK 27(2026年9月)
下一个 LTS JDK 29(预计 2027年9月)
主要意义 后 LTS 创新版本,引入 HTTP/3 和延迟常量等重要特性

JDK 26 的关键贡献

  1. HTTP/3 原生支持 --- Java 网络编程进入 QUIC 时代
  2. AOT 对象缓存 --- 启动加速从类级别扩展到对象级别
  3. G1 GC 吞吐量提升 --- 双卡表机制减少同步开销
  4. Final 字段完整性 --- 加强不可变性保证
  5. Lazy Constants --- 优雅的延迟初始化方案
  6. Structured Concurrency 超时 --- 更实用的并发超时处理
  7. PEM Encoding API --- 密码学对象编码标准化
  8. 移除 Applet API --- 清理历史遗留

总结 :JDK 26 是 JDK 25 LTS 之后的第一个创新版本,在多个方向带来重要突破。HTTP/3 客户端 让 Java 原生支持基于 QUIC 的现代网络协议;AOT 对象缓存 将启动加速从类加载扩展到对象级别;Lazy Constants 提供了优雅的延迟初始化方案,替代了复杂的 DCL 和 Holder 模式;G1 GC 吞吐量提升 让默认 GC 在高并发场景下表现更好;Final 字段完整性 加强了 Java 的不可变性保证。结构化并发和原始类型模式等预览特性继续演进,为后续版本定稿做准备。

相关推荐
马优晨2 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区3 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大4 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai4 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
维天说4 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
এ慕ོ冬℘゜4 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa4 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio
一次旅行4 小时前
Python+大模型端到端自动化日报系统
开发语言·python·自动化
Zane19945 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端