JDK 26 于 2026 年 3 月发布,是 JDK 25(LTS)之后的第一个非 LTS 版本。
本版本共有 10 个 JEP,其中 5 个正式特性、4 个预览特性、1 个孵化特性。
JDK 26 在并发、网络、性能和安全方面均有重要改进。
JEP 517 — HTTP/3 Client(HTTP/3 客户端)。JDK 26 为 java.net.http.HttpClient 添加了 HTTP/3 协议支持,基于 QUIC 传输协议。
改进:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
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(); })); }
// 处理结果... } |
JEP 516 — AOT Object Caching(AOT 对象缓存)。JDK 26 扩展了 JDK 24 引入的 AOT 机制,支持缓存对象(不仅是类),并兼容所有 GC。
改进:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# ============ 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 中生成缓存 |
JEP 522 — G1 GC Throughput Improvement(G1 GC 吞吐量提升)。JDK 26 通过减少同步开销(双卡表机制)显著提升了 G1 GC 的吞吐量。
改进:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# ============ 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 |
JEP 500 — Final Field Integrity(终态字段完整性)。JDK 26 加强了 final 字段的不可变性保证,通过反射修改 final 字段时会产生警告。
改进:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
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 字段 |
JEP 504 — Remove the Applet API(移除 Applet API)。JDK 26 彻底移除了 java.applet 包中的所有类。
改进:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
// ============ 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 年 |
JEP 525 — Structured Concurrency(结构化并发,第六次预览)。JDK 26 为结构化并发添加了超时支持(Joiner 超时),进一步简化并发编程。
改进:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
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(); }); |
JEP 530 — Primitive Types in Patterns(原始类型模式,第四次预览)。JDK 26 继续改进原始类型在模式匹配中的支持,接近最终定稿。
改进:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
// ============ 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 |
JEP 524 — PEM Encoding of Cryptographic Objects(PEM 编码 API,第二次预览)。JDK 26 继续改进 PEM 编码/解码 API,支持将密码学对象与 PEM 格式互相转换。
改进:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
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()); |
JEP 526 — Lazy Constants(延迟常量,第二次预览)。JDK 26 引入 LazyConstant API,提供线程安全的延迟初始化机制,替代 static final 急切初始化和双重检查锁定模式。
改进:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
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 |
JEP 529 — Vector API(向量 API,第十一次孵化)。JDK 26 继续孵化向量 API,等待 Project Valhalla 值类型支持后正式标准化。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
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 |
| 序号 | 特性 | 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 | — | 预览 | 正式 | — |
| 项目 | 说明 |
|---|---|
| 发布日期 | 2026年3月 |
| 版本类型 | 非 LTS(短期支持) |
| 前一个版本 | JDK 25(LTS,2025年9月) |
| 下一个版本 | JDK 27(2026年9月) |
| 下一个 LTS | JDK 29(预计 2027年9月) |
| 主要意义 | 后 LTS 创新版本,引入 HTTP/3 和延迟常量等重要特性 |
JDK 26 的关键贡献:
总结:JDK 26 是 JDK 25 LTS 之后的第一个创新版本,在多个方向带来重要突破。HTTP/3 客户端 让 Java 原生支持基于 QUIC 的现代网络协议;AOT 对象缓存 将启动加速从类加载扩展到对象级别;Lazy Constants 提供了优雅的延迟初始化方案,替代了复杂的 DCL 和 Holder 模式;G1 GC 吞吐量提升 让默认 GC 在高并发场景下表现更好;Final 字段完整性 加强了 Java 的不可变性保证。结构化并发和原始类型模式等预览特性继续演进,为后续版本定稿做准备