JDK 26 新特性详解
JDK 26 于 2026 年 3 月发布,是 JDK 25(LTS)之后的第一个非 LTS 版本。
本版本共有 10 个 JEP,其中 5 个正式特性、4 个预览特性、1 个孵化特性。
JDK 26 在并发、网络、性能和安全方面均有重要改进。
目录
- [HTTP/3 Client HTTP/3 客户端](#HTTP/3 Client HTTP/3 客户端)
- [AOT Object Caching AOT 对象缓存](#AOT Object Caching AOT 对象缓存)
- [G1 GC Throughput Improvement G1 吞吐量提升](#G1 GC Throughput Improvement G1 吞吐量提升)
- [Final Field Integrity 终态字段完整性](#Final Field Integrity 终态字段完整性)
- [Remove Applet API 移除 Applet API](#Remove Applet API 移除 Applet API)
- [Structured Concurrency 结构化并发(第六次预览)](#Structured Concurrency 结构化并发(第六次预览))
- [Primitive Types in Patterns 原始类型模式(第四次预览)](#Primitive Types in Patterns 原始类型模式(第四次预览))
- [PEM Encoding API PEM 编码 API(第二次预览)](#PEM Encoding API PEM 编码 API(第二次预览))
- [Lazy Constants 延迟常量(第二次预览)](#Lazy Constants 延迟常量(第二次预览))
- [Vector API 向量 API(第十一次孵化)](#Vector API 向量 API(第十一次孵化))
- [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(第四次预览)
instanceof和switch全面支持所有原始类型- 安全的窄化转换匹配
- 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 的关键贡献:
- HTTP/3 原生支持 --- Java 网络编程进入 QUIC 时代
- AOT 对象缓存 --- 启动加速从类级别扩展到对象级别
- G1 GC 吞吐量提升 --- 双卡表机制减少同步开销
- Final 字段完整性 --- 加强不可变性保证
- Lazy Constants --- 优雅的延迟初始化方案
- Structured Concurrency 超时 --- 更实用的并发超时处理
- PEM Encoding API --- 密码学对象编码标准化
- 移除 Applet API --- 清理历史遗留
总结 :JDK 26 是 JDK 25 LTS 之后的第一个创新版本,在多个方向带来重要突破。HTTP/3 客户端 让 Java 原生支持基于 QUIC 的现代网络协议;AOT 对象缓存 将启动加速从类加载扩展到对象级别;Lazy Constants 提供了优雅的延迟初始化方案,替代了复杂的 DCL 和 Holder 模式;G1 GC 吞吐量提升 让默认 GC 在高并发场景下表现更好;Final 字段完整性 加强了 Java 的不可变性保证。结构化并发和原始类型模式等预览特性继续演进,为后续版本定稿做准备。
