一、JDK 21 新特性说明
JDK 21 已经于 2023 年 9 月 19 日正式发布,Java 21 / JDK 21 已正式 GA,此版本是继 JDK 17 后的长期支持版本 (LTS),Oracle 将为其提供至少八年的技术支持和更新。本文总结了 JDK 21 发布的新特性。
二、JDK 21 正式稳定功能
-
JEP 431:序列集合
序列集合(Sequenced Collections)在 core-libs/java.util:collections 包中。
该 JEP 提议引入 “一个新的接口族,用于表示集合的概念,这些集合的元素按照预定义的序列或顺序排列,它们是作为集合的结构属性。” 这一提案的动机是由于集合框架中缺乏预定义的顺序和统一的操作集。 -
JEP 439:分代 ZGC
分代 ZGC(Generational ZGC)在 hotspot/gc 包中。
通过扩展 Z 垃圾回收器(ZGC)来维护年轻对象和年老对象的独立生成,从而提高应用程序性能。这将使 ZGC 能够更频繁地收集年轻对象 —— 这些对象往往英年早逝。 -
JEP 440:记录模式
使用记录模式(Record Patterns)增强 Java 编程语言,以解构记录值。可以嵌套记录模式和类型模式,以实现功能强大、声明性和可组合形式的数据导航和处理。
下面我们通过一个例子来理解这个新特性:
record Point(int x, int y) {}
static void printSum(Object obj) {
if (obj instanceof Point p) {
int x = p.x();
int y = p.y();
System.out.println(x+y);
}
}
上述代码中定义了一个名为 Point 的 record 类(Java 16 中的新特性),如果我们想要获取、操作或者打印 Point 中的 x 和 y 的话。就不得不先完成类型判断和类型转换。所以,这里为了实现 x+y 总共需要 4 行代码。而在 Java 21 之后,只需要 2 行代码就能完成:
static void printSum(Object obj) {
if (obj instanceof Point(int x, int y)) {
System.out.println(x+y);
}
}
可以看到,类型判断、类型转换、record 值的结构都一气呵成了,所以代码量得到了简化。
-
JEP 441:switch 模式匹配
通过 switch 表达式和语句的模式匹配来增强 Java 编程语言。通过将模式匹配扩展到 switch,可以针对多个模式测试表达式,每个模式都有一个特定的操作,从而可以简洁、安全地表达复杂的面向数据的查询。 -
JEP 444:虚拟线程
将虚拟线程(Virtual Threads)引入 Java 平台。虚拟线程是轻量级线程,可以显著减少编写、维护和观察高吞吐量并发应用程序的工作量。虚拟线程已经成为了 Java 社区中火热的话题。虚拟线程会改变 Java 的多线程编程。虚拟线程会成为 Java 21 的杀手锏功能,促使更多用户升级到 Java 21。
以下是一个创建大量虚拟线程的示例程序。该程序首先获得一个ExecutorService将为每个提交的任务创建一个新的虚拟线程。然后它提交 10,000 个任务并等待它们全部完成:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
}
本例中的任务是简单的代码——休眠一秒钟——现代硬件可以轻松支持 10,000 个虚拟线程并发运行此类代码。在幕后,JDK 在少量操作系统线程上运行代码,可能只有一个线程。
虚拟线程可以在以下情况下显着提高应用程序吞吐量:
- 任务并发数高(几千以上),并且工作负载不受 CPU 限制,因为在这种情况下,拥有比处理器内核多得多的线程无法提高吞吐量。
虚拟线程有助于提高典型服务器应用程序的吞吐量,因为此类应用程序包含大量并发任务,这些任务的大部分时间都在等待。
虚拟线程可以运行平台线程可以运行的任何代码。特别是,虚拟线程支持线程局部变量和线程中断,就像平台线程一样。这意味着处理请求的现有 Java 代码将很容易地在虚拟线程中运行。许多服务器框架会选择自动执行此操作,为每个传入请求启动一个新的虚拟线程,并在其中运行应用程序的业务逻辑。
-
JEP 449:弃用 Windows 32 位 x86 移植
弃用 Windows 32 位 x86 移植,并打算在将来的版本中将其删除。 -
JEP 451:准备禁止动态加载代理
将代理动态加载到正在运行的 JVM 中时发出警告。这些警告旨在让用户为将来的版本做好准备,该版本默认情况下不允许动态加载代理,以提高默认情况下的完整性。在启动时加载代理的可服务性工具不会导致在任何版本中发出警告。 -
JEP 452:密钥封装机制 API
介绍一种用于密钥封装机制(Key Encapsulation Mechanism,简称 KEM)的 API,这是一种使用公钥加密来保护对称密钥的加密技术。
二、JDK 21 预览阶段功能
-
JEP 430:字符串模板(预览)
使用字符串模板(String Templates)增强 Java 编程语言。字符串模板通过将文本与嵌入的表达式和模板处理器耦合来生成专门的结果,从而补充 Java 现有的字符串文本和文本块。这是一个预览语言功能和 API。 -
JEP 442:外部函数和内存 API(第三次预览)
引入 API,Java 程序可以通过该 API 与 Java 运行时之外的代码和数据进行互操作。通过有效地调用外部函数(即 JVM 外部的代码),并通过安全地访问外部内存(即不受 JVM 管理的内存),API 使 Java 程序能够调用本机库并处理本机数据,而不会出现 JNI 的脆弱性和危险性。这是一个预览 API。 -
JEP 443:未命名模式和变量(预览)
使用未命名模式和未命名变量来增强 Java 语言,未命名模式匹配记录组件而不说明组件的名称或类型,未命名变量可以初始化但不使用。两者都用下划线字符_表示。这是一个预览语言功能。 -
JEP 445:未命名类和实例主方法(预览)
发展 Java 语言,使学生无需理解为大型程序设计的语言功能即可编写第一个程序。学生们不用使用单独的 Java 方言,就可以为单类程序编写精简的声明,然后随着技能的发展,无缝地扩展程序,使用更高级的功能。这是一个预览语言功能。 -
JEP 446:作用域值(预览)
引入作用域值,这些值可以在不使用方法参数的情况下安全有效地共享给方法。它们优先于线程化局部变量,尤其是在使用大量虚拟线程时。这是一个预览 API。
实际上,作用域值是一个隐式方法参数。这 “就好像” 一系列调用中的每个方法都有一个额外的、不可见的参数。没有任何方法声明此参数,只有能够访问作用域值对象的方法才能访问其值(数据)。通过作用域值,可以通过一系列中间方法将数据从调用者安全地传递给遥远的被调用者,这些中间方法不声明数据的参数,也无法访问数据。 -
JEP 453:结构化并发(预览)
通过引入用于结构化并发(Structured Concurrency)的 API 来简化并发编程。结构化并发将在不同线程中运行的相关任务组视为单个工作单元,从而简化错误处理和消除,提高可靠性,并增强可观察性。这是一个预览 API。
三、孵化阶段功能
JEP 448:Vector API(孵化器第六阶段)
引入 API 来表示向量计算,这些向量计算在运行时可靠地编译为支持的 CPU 架构上的最佳向量指令,从而实现优于等效标量计算的性能。
参考引用
Download: https://jdk.java.net/21/ Release notes:
https://jdk.java.net/21/release-notes Features:
https://openjdk.org/projects/jdk/21/