JDK 21:Java 21 中的新特性


Java Development Kit (JDK) 21 将于 9 月作为 Oracle 标准 Java 实现的下一个长期支持版本发布,现在正式为其提议了 16 个特性,最近几天又增加了三个特性。

  • 结构化并发,在预览阶段,通过用于结构化并发的 API 简化了并发编程,将在不同线程中运行的相关任务组视为一个工作单元。这简化了错误处理和取消,提高了可靠性并增强了可观察性。
    结构化并发此前孵化于JDK 20JDK 19,分别于2022年3月和2022年9月发布;它将作为util.concurrent包中的预览 API。这次唯一的重大变化是 StructuredTaskScope ::(…)方法返回一个[Subtask]而不是Future。
    结构化并发的目标包括推广一种并发编程风格,可以消除取消和关闭引起的常见风险,例如线程泄漏和取消延迟,并提高并发代码的可观察性。
  • Scoped values也处于预览状态,将支持在线程内和线程间共享不可变数据。它们优于线程局部变量,尤其是在使用大量虚拟线程时。线程局部变量具有设计缺陷,包括无约束的可变性、无限制的生命周期和昂贵的继承。作用域值允许在大型程序中的组件之间安全地共享数据,而无需求助于方法参数。该提案在 JDK 20 中孵化。该计划的目标包括易用性、可理解性、健壮性和性能。
  • 当代理被动态加载到正在运行的 JVM 中时,名为“准备禁止代理的动态加载”的提案要求发出警告。这些警告的目的是为未来的版本做准备,该版本默认不允许动态加载代理,以提高默认的完整性。该提案的其他目标包括重新评估可服务性和完整性之间的平衡,可服务性涉及到对运行中的代码的临时改变,而完整性则假定运行中的代码不被任意改变,并确保大多数不需要动态加载代理的工具不受影响。该计划还要求将动态加载代理的能力与其他所谓的 "superpower"的能力保持一致,如深度反射。
    代理是一个可以在应用程序运行时改变应用程序代码的组件;这些组件是由2004年JDK 5中的Java平台剖析架构引入的,作为工具(特别是剖析器)对类进行分析的一种方式。虽然代理在设计时考虑到了良性的工具,但高级开发人员发现了一些使用案例,如面向方面的编程,以任意的方式改变应用程序的行为。
    也没有什么可以阻止代理改变应用程序之外的代码,例如JDK本身的代码。
    JDK 5要求在命令行中指定代理,以确保应用程序的所有者批准使用代理。
    在JDK 21中,计划要求动态加载代理必须得到应用程序所有者的批准,就像在启动时加载代理一样。这一变化将使Java平台更接近于默认的完整性。
  • 密钥封装机制 API,一种通过公共密码术保护对称密钥的加密技术。该提案的一个目标是使应用程序能够使用 KEM 算法,例如 RSA 密钥封装机制 (RSA-KEM)、椭圆曲线集成加密方案 (ECIES) 以及美国国家标准与技术研究院 (NIST) 的候选算法后量子密码标准化过程。另一个目标是在更高级别的协议(例如传输层安全性 (TLS))和加密方案(例如混合公钥加密 (HPKE))中启用 KEM。此外,安全提供商将能够在 Java 代码或本机代码中实施 KEM 算法,并包括RFC 9180中定义的 Diffie-Hellman KEM (DHKEM) 的实施。
  • 弃用用于删除的 Windows 32 位 x86 端口,目的是在将来的版本中将其删除。该提案旨在更新构建系统,以便在尝试为 Windows 32 位 x86 配置构建时发出错误消息。该消息将通过一个新的配置选项被抑制。此外,计划将端口和相关的端口特定功能标记为已弃用,以便在相关文档中删除。该提案指出,Windows 10 是最后一个支持 32 位操作的 Windows 操作系统,其生命周期将于 2025 年 10 月结束。
  • Generational Shenandoah , 一个增强Shenandoah GC 的提案具有实验性的分代垃圾收集功能,以提高可持续的吞吐量、负载峰值弹性和内存利用率。
    该提案的主要目标是在不破坏非分代 Shenandoah 的情况下提供一种实验性分代模式,目的是使分代模式成为未来版本中的默认模式。其他目标包括在不牺牲低 GC 暂停的情况下减少持续内存占用、降低分配峰值期间发生退化和完整收集的风险、减少 CPU 和电源使用、维持高吞吐量以及继续支持压缩对象指针。
    该提案最初将支持 x64 和 AArch64,随着实验模式的推进准备就绪,会添加对其他指令集的支持。取代非分代 Shenandoah 不是目标,它将继续作为默认操作模式,其性能或功能不会退化。提高每个可以想象的工作负载的性能也不是目标。
  • 未命名类和实例主要方法的预览,以改进语言,以便学生能够编写他们的第一个 Java 程序,而无需了解为大型程序设计的语言功能。学生无需使用单独的 Java 方言,就可以为单类程序编写简化的声明,然后随着技能的增长无缝地扩展程序以使用更高级的功能。目的是为 Java 提供一个平滑的入口。
  • 未命名模式和变量的预览。未命名的模式匹配一​​个记录组件而不声明组件的名称或类型,而未命名的变量可以被初始化但不能使用。两者都用下划线字符 . 表示_。该提案旨在通过消除不必要的嵌套模式来提高记录模式的可读性,并通过识别必须声明但不会使用的变量来提高所有代码的可维护性。
  • Generational ZGC旨在通过扩展 ZGC 以维护新旧对象的不同代来提高应用程序性能。年轻的对象往往会早逝,保持不同的世代将使 ZGC 更频繁地收集它们。使用分代 ZGC 运行的应用程序应该会看到以下好处:分配停顿的风险降低、所需的堆内存开销降低以及垃圾收集 CPU 开销降低。与非分代 ZGC 相比,这些好处应该不会显着降低吞吐量。
  • 在JDK 19和JDK 20中预览的记录模式将解构记录值。可以嵌套记录模式和类型模式,以实现强大的、声明式的和可组合的数据导航和处理形式。该提案的目标包括扩展模式匹配以解构记录类的实例并添加嵌套模式,从而实现更多可组合的数据查询。此功能与 switch 的模式匹配共同发展。当前 JEP(JDK 增强提案)中的记录模式建议根据持续的经验和反馈进一步完善该功能。除了较小的编辑更改外,自第二次预览以来的主要更改是删除了对出现在增强的标题中的记录模式的支持for陈述。该功能可能会在未来的 JEP 中重新提出。
  • switch 的模式匹配使一个switch表达式或语句能够针对多个模式进行测试,每个模式都有特定的操作,因此可以安全、简洁地表达复杂的面向数据的查询。
    此功能最初是在JDK 17中提出的,随后在JDK 18 、JDK 19 和 JDK 20中得到完善。它将在 JDK 21 中最终确定,并根据反馈和经验进一步完善。
    与以前的JEP相比,主要的变化是取消了括号内的模式,并允许合格的枚举常量,如switch表达式和语句的case常量。目标包括通过允许模式出现在case标签中来扩展switch表达式和语句的表现力和适用性,允许在需要时放宽switch的历史无效性,并通过要求模式switch语句覆盖所有潜在的输入值来提高switch语句的安全性。另一个目标是确保现有的switch表达式和语句能够继续编译而不发生变化,并以相同的语义执行。
  • Vector API的第六个孵化器,用于表达矢量计算,这些计算在运行时可靠地编译为支持的 CPU 架构上的最佳矢量指令,实现优于等效标量计算的性能。这之前已经在J​​DK 16到 JDK 20 中孵化。最新版本包括性能增强和错误修复。该提案的目标包括清晰简洁、与平台无关,以及在 x64 和 AArch64 架构上提供可靠的运行时编译和性能。其他目标包括优雅降级,当向量计算无法在运行时完全表示为向量指令序列时,以及与Project Valhalla对齐。
  • 外部函数和内存 API使 Java 程序能够与 Java 运行时之外的代码和数据进行互操作。通过高效地调用外部函数和安全地访问外部内存,这个预览 API 使 Java 程序能够调用本地库和处理本地数据,而没有 JNI(Java Native Interface)的脆弱性和危险性。
    该 API 之前在JDK 20 和JDK 19中进行过预览。最新预览版中的改进包括增强的布局路径和取消引用地址布局的新元素、Arena 界面中原生段生命周期的集中管理、后备原生链接器实现以及移除VaList. 该提案的目标包括易用性、性能、通用性和安全性。在此 API 之上重新实现 JNI 或以任何方式更改 JNI 都不是目标。
  • 虚拟线程是轻量级线程,有望“显着”减少编写、维护和观察高吞吐量并发应用程序的工作量。该计划的目标包括使以简单的每个请求一个线程的方式编写的服务器应用程序能够以接近最佳的硬件利用率进行扩展,使使用 API 的现有代码能够以最小的变化采用虚拟线程,并使虚拟线程的调试和分析变得lang.Thread容易使用当前 JDK 工具的线程。
    之前在JDK 20JDK 19中都有预览,虚拟线程将在 JDK 21 中完成。随着 JDK 21,虚拟线程现在支持线程局部变量所有的时间,并且不可能创建没有这些变量的虚拟线程。对线程局部变量的保证支持确保更多现有库可以不加改动地用于虚拟线程,并有助于将面向任务的代码迁移到使用虚拟线程。
  • 序列化集合引入了接口来表示具有定义的遇到顺序的集合。每个集合都有明确定义的第一个和第二个元素,依此类推,直到最后一个元素。提供了统一的 API 来接受第一个和最后一个元素并以相反的顺序处理元素。
    激发该提案的是 Java 的集合框架的情况缺少一个集合类型来表示具有定义的遇到顺序的元素序列。它还缺乏适用于这些集合的统一操作集。这些差距一直是一个问题,也是投诉的来源。该提案要求定义用于集合、集合和映射排序的接口,并将其改装到现有的集合类型层次结构中。所有这些新方法都有默认实现。
  • 字符串模板作为预览功能出现,通过将文字文本与嵌入式表达式和处理器相结合来生成专门的结果,从而补充 Java 现有的字符串文字和文本块。此语言功能和 API 旨在通过简化 Java 程序的编写,使表达包含运行时计算值的字符串变得容易。它承诺增强表达式的可读性、提高程序安全性、保持灵活性并简化接受以非 Java 语言编写的字符串的 API 的使用。实现从组合文字文本和嵌入表达式派生的非字符串表达式的开发也是一个目标。

最终列表见这里,下图是未命名类带来的最大Java简化写法,适合初入门者(类似Rust)