
就在前两天,JDK 26 正式发布了!这是一个非长期支持版。上一个长期支持版是 JDK 25,下一个长期支持版预计是 JDK 29。

JDK 26 版本带来了10个值得关注的新特性,涵盖了网络、性能、语言、并发和安全等多个方面,下面将为你逐一详细解读。
JDK 26 十大新特性概览
- JEP 517: HTTP/3 for the HTTP Client API (为 HTTP Client API 引入 HTTP/3 支持)
- JEP 522: G1 GC: Improve Throughput by Reducing Synchronization (G1 GC 吞吐量优化)
- JEP 516: Ahead-of-Time Object Caching with Any GC (AOT 对象缓存支持任意 GC)
- JEP 500: Prepare to Make Final Mean Final (准备让 final 真正不可变)
- JEP 526: Lazy Constants (延迟常量,第二次预览)
- JEP 525: Structured Concurrency (结构化并发,第六次预览)
- JEP 530: Primitive Types in Patterns, instanceof, and switch (模式匹配支持基本类型,第四次预览)
- JEP 524: PEM Encodings of Cryptographic Objects (加密对象 PEM 编码,第二次预览)
- JEP 529: Vector API (向量 API,第十一次孵化)
- JEP 504: Remove the Applet API (移除 Applet API)
下图直观展示了从 JDK 8 到 JDK 25 各版本的特性数量与更新节奏:

JEP 517: 为 HTTP Client API 引入 HTTP/3 支持
JDK 26 为 java.net.http.HttpClient API 正式添加了 HTTP/3 支持,这是一个期待已久的重要更新。
HTTP/3 的核心优势:
- 基于 QUIC 协议:不同于 HTTP/2 的 TCP 基础,HTTP/3 建立在 QUIC(Quick UDP Internet Connections)协议之上。QUIC 在 UDP 的基础上集成了加密、可靠传输等机制,连接和传输延迟更低。
- 消除队头阻塞:HTTP/2 中,一个 TCP 连接上的多路复用请求可能会因为单个包的丢失而被整体阻塞。HTTP/3 利用 QUIC 的流(Stream)独立性,让各个数据流互不影响,从而有效缓解了队头阻塞问题。
- 更快的连接建立:得益于 TLS 1.3 与 QUIC 的融合,连接建立可以做到 0-RTT 或 1-RTT,比传统 TCP+TLS 的 3个RTT 要快得多。
- 更强的移动端适应性:QUIC 连接使用连接 ID 标识,而非传统的四元组(源/目的IP和端口)。这意味着即使网络环境切换(如从 Wi-Fi 到移动网络),只要连接 ID 不变,连接就可以无缝迁移,不会中断。
使用方式:
使用非常简单,HttpClient 会自动协商使用最高版本的 HTTP 协议,几乎无需修改现有代码:
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.build();
// 如果服务器支持 HTTP/3,HttpClient 会自动升级使用
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
当然,你也可以明确指定优先使用 HTTP/3:
// 构建客户端时指定默认版本
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_3) // 明确指定 HTTP/3
.build();
// 或者在单个请求中指定
HttpRequest request = HttpRequest.newBuilder(URI.create("https://javaguide.cn/"))
.version(HttpClient.Version.HTTP_3)
.GET().build();
JEP 522: G1 GC 吞吐量优化
自 JDK9 起,G1 垃圾收集器便成为了默认的垃圾收集器。 它致力于在延迟和吞吐量之间取得平衡。为了减少 GC 暂停,G1 会更多地与应用线程并发工作,这引入了同步开销,可能影响吞吐量。
JEP 522 引入了双卡表(Card Table)机制来优化这个问题:
- 第一张卡表:应用线程的写屏障在更新这张卡表时无需任何同步,使写屏障代码更简单、更快速。
- 第二张卡表:优化器线程在后台并行处理这张初始为空的卡表。
当 G1 预测扫描第一张卡表可能超出暂停时间目标时,它会原子性地交换两张卡表。之后,应用线程继续更新新的空表,而优化器线程处理已满的旧表,双方均无需额外同步。
性能提升效果:
- 在频繁修改对象引用字段的应用中,吞吐量提升 5-15%。
- 即使在不频繁修改的场景,由于写屏障简化(x64架构上指令数从约50条降至12条),吞吐量也能提升高达 5%。
- GC 暂停时间也有轻微下降。
内存开销:
第二张卡表与第一张容量相同,每张卡表需要 Java 堆容量的 0.2%。例如,每 1GB 堆内存会额外使用约 2MB 的原生内存。
JEP 516: AOT 对象缓存支持任意 GC
这是 Project Leyden 的重要里程碑,它使得提前(AOT)对象缓存能够与任意垃圾收集器配合使用。
此前,JDK 24 引入的 AOT 类数据共享(JEP 483)仅支持 G1 垃圾收集器,因为缓存中存储的对象引用是物理内存地址。不同 GC(如 ZGC)的内存布局和对象移动策略不同,导致兼容性问题。
JEP 516 的核心改进在于将对象引用的存储方式从物理内存地址改为逻辑索引:
- 使用 GC 无关的流式格式存储缓存。
- 缓存可以在运行时被任意 GC 加载和解析。
- JVM 在加载时将逻辑索引转换为实际的内存地址。
带来的收益:
- 启动时间优化:显著减少 Java 应用的冷启动时间。
- 支持 ZGC:低延迟的 ZGC 现在也能享受 AOT 缓存带来的启动加速。
- 云原生友好:对于微服务、无服务器函数等启动时间敏感的场景特别有价值。
JEP 500: 准备让 final 真正不可变
这个特性为 Java 的完整性优先原则铺路,旨在让 final 字段变得真正不可变。
自 JDK 1.0 起,final 字段实际上可以通过深度反射被修改,这破坏了其不可变性的语义保证,也阻碍了编译器的优化。以下代码展示了这种“魔法”:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
class Example {
private final String name = "Original";
public String getName() {
return name;
}
}
// 通过反射修改 final 字段
Example example = new Example();
Field field = Example.class.getDeclaredField("name");
field.setAccessible(true);
// 移除 final 修饰符
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(example, "Modified"); // 成功修改了 final 字段!
System.out.println(example.getName()); // 输出 "Modified"
在 JDK 26 中,当通过深度反射修改 final 字段时,JVM 会发出警告。这是为未来版本默认禁止此类操作所做的准备。对于某些框架(如序列化、测试工具)确实需要此能力的场景,JDK 26 提供了显式的选择机制,允许开发者在过渡期继续使用,同时为未来的严格模式做好准备。
JEP 526: 延迟常量 (第二次预览)
该特性在 JDK 25 中首次预览(JEP 501),JDK 26 是其第二次预览。
传统的 static final 字段在类加载时就会初始化,这可能带来问题:增加启动时间、浪费从未使用的常量内存,以及迫使开发者编写复杂的延迟初始化代码(如双重检查锁定)。
JEP 526 引入了 LazyConstant<T>,它是一种持有不可变数据的对象,JVM 将其视为真正的常量,从而获得与声明 final 字段相同的优化待遇。
// 传统方式:类加载时立即初始化
static final ExpensiveObject TRADITIONAL = new ExpensiveObject();
// 新方式:首次访问时才初始化
static final LazyConstant<ExpensiveObject> LAZY =
LazyConstant.of(() -> new ExpensiveObject());
// 使用时
ExpensiveObject obj = LAZY.get(); // 此时才进行初始化
优势:
- 按需初始化:提升启动性能。
- 线程安全:内置线程安全保证,无需手动同步。
- JVM 优化:JVM 可以像对待
final 字段一样优化它。
- 代码简化:消除了双重检查锁定等复杂的延迟初始化模式。
JEP 525: 结构化并发 (第六次预览)
结构化并发是一种旨在简化多线程编程的方法,它并非要取代 java.util.concurrent,而是提供一种更结构化的方式来处理并发任务。该特性自 JDK 19 引入,目前处于孵化阶段。
结构化并发将多个在独立线程中运行的任务视为一个单一的工作单元。这样做简化了错误处理,提高了可靠性,并保留了单线程代码的可读性和可维护性。
其核心 API 是 StructuredTaskScope,它支持将任务拆分为多个并发子任务执行,并确保子任务必须在主任务继续之前完成(或随主任务一起失败)。
基本用法如下:
try (var scope = new StructuredTaskScope<Object>()) {
// 使用fork方法派生线程来执行子任务
Future<Integer> future1 = scope.fork(task1);
Future<String> future2 = scope.fork(task2);
// 等待所有子线程完成
scope.join();
// 处理结果或异常
... process results/exceptions ...
} // 作用域结束时会自动关闭
结构化并发与虚拟线程(轻量级线程)配合使用尤其高效。
JDK 26 中的新变动:
- Joiner 增强:
Joiner 接口新增 onTimeout() 方法,允许在超时发生时返回特定结果。
- 返回类型优化:
allSuccessfulOrThrow() 现在直接返回结果列表(List),而非之前的子任务流。
- API 简化:将
anySuccessfulResultOrThrow() 简化为 anySuccessfulOrThrow()。
JEP 530: 模式匹配支持基本类型 (第四次预览)
该特性在 JDK 23 中首次预览(JEP 455),JDK 26 是其第四次预览。
模式匹配现在可以在 switch 和 instanceof 语句中处理所有的基本数据类型(如 int, double, boolean 等),使得代码更安全、更简洁。
static void test(Object obj) {
if (obj instanceof int i) {
System.out.println("这是一个int类型: " + i);
}
}
JDK 26 的增强:
- 消除了多项与基本类型相关的限制,使模式匹配、
instanceof 和 switch 更加统一和富有表达力。
- 增强了“无条件精确性”的定义。
- 在
switch 构造中应用更严格的支配性检查,使编译器能够识别并减少更广泛的编码错误。
JEP 524: 加密对象 PEM 编码 (第二次预览)
该特性在 JDK 25 中首次预览(JEP 518),JDK 26 是其第二次预览。
PEM(Privacy-Enhanced Mail)是一种广泛使用的文本格式,用于存储和传输证书、私钥等加密对象。JEP 524 提供了一个新的 API,用于在加密对象和 PEM 格式之间进行编码和解码。
// 将密钥编码为 PEM 格式
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair keyPair = kpg.generateKeyPair();
// 编码为 PEM
String pemEncoded = PemEncoding.encode(keyPair.getPrivate());
// 从 PEM 解码
PrivateKey decodedKey = PemEncoding.decode(pemEncoded);
这个 API 简化了加密对象的处理,减少了错误风险,并增强了安全 Java 应用程序在企业、云环境中的可移植性和互操作性。
JEP 529: Vector API (向量 API,第十一次孵化)
向量 API 用于表达向量计算,这些计算可以在运行时编译为 CPU 架构上的最佳向量指令(如 SIMD),从而获得远超等效标量计算的性能。其目标是提供简洁、易用且平台无关的向量计算表达方式。
这是一个简单的标量计算:
void scalarComputation(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;
}
}
这是使用 Vector API 的等效向量计算:
static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;
void vectorComputation(float[] a, float[] b, float[] c) {
int i = 0;
int upperBound = SPECIES.loopBound(a.length);
for (; i < upperBound; i += SPECIES.length()) {
// FloatVector va, vb, vc;
var va = FloatVector.fromArray(SPECIES, a, i);
var vb = FloatVector.fromArray(SPECIES, b, i);
var vc = va.mul(va)
.add(vb.mul(vb))
.neg();
vc.intoArray(c, i);
}
for (; i < a.length; i++) {
c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;
}
}
尽管仍处于孵化阶段(第十一次迭代),但 Vector API 对于科学计算、机器学习、AI 推理等性能敏感领域至关重要,它使得 Java 能够编写出接近本地语言性能的代码。
JEP 504: 移除 Applet API
Applet API 在 JDK 9 中被标记为废弃,在 JDK 17 中被标记为“即将移除”。在 JDK 26 中,这个古老的 API 终于被完全移除。
这意味着:
java.applet.Applet 类及其相关类已被删除。
- 减小了 JDK 的安装和源代码体积。
- 提升了应用程序整体的性能、稳定性和安全性。
Applet 技术早已过时,现代 Web 开发已完全转向其他技术栈。移除这个遗留 API 是 Java 平台现代化的必要一步。
总结
JDK 26 虽然是一个非 LTS 版本,但包含了一系列扎实且面向未来的重要更新:
| 类别 |
特性 |
| 网络 |
HTTP/3 支持 |
| 性能 |
G1 GC 吞吐量优化、AOT 缓存支持任意 GC |
| 语言 |
模式匹配支持基本类型(第四次预览)、延迟常量(第二次预览) |
| 并发 |
结构化并发(第六次预览)、向量 API(第十一次孵化) |
| 安全 |
让 final 真正不可变、PEM 编码支持 |
| 清理 |
移除 Applet API |
根据 Oracle 的支持政策,JDK 26 将获得更新支持直至 2026 年 9 月,之后将被 JDK 27 取代。对于开发者而言,及时了解这些新特性,有助于在合适的时机将其应用于项目,以提升性能、安全性和开发体验。