Java 21 重磅发布:全面拥抱虚拟线程
首先,感谢一下不少xdm私信关心我的身体状况,我也不是什么厉害的大佬,点开通知看到一堆私信还是蛮感动的。
近来有意大幅缩短了更新频率,增加了日常调养身体的时间,淋巴结确实变小了,睡眠也逐渐正常,每晚23:30-00:00之间就可以自然入睡,所以精神也好了许多。
上周感冒比较严重,这周才好转,加上一直以来的胃病还没好,这具身体着实千疮百孔,令人叹息,慢慢来吧,xdm在学习之余也要保重自己哦。
本篇不包含任何案例说明,因为我认为几年内Java21不会在国内有广泛应用,所以暂时不需要去学习它,相反,Java17的一些新特性可以考虑学习下,我之前的文章里面已经有这样的专题。
之所以要了解这种重大改进的新版本,目的是为了确定Java未来的趋势走向,就比如之前lamaba表达式和stream流的出现,基本能确定是一种趋势,事实证明也确实如此。
正式发布在今年9月19日Oracle宣布Java21正式发布,JavaSE的产品经理对于这次版本发布做了全面的说明。
首先是对Java21的一个社区贡献做了说明,在Java21中,标记为已修复的2,585个JIRA问题中,Oracle完成了1,868个问题,而Java社区的其他成员贡献了717个问题。
可以看出来,Java社区非官方的贡献度超过官方团队的三分之一,活跃度依旧是挺高的。
接下来甲骨文着重感谢了一些知名IT公司的研发团队对于Java21的贡献和支持,感谢了亚马逊、ARM、Azul、谷歌、华为、IBM、英特尔、ISCAS、红帽、Rivos、SAP和腾讯等公司的开发人员做出的杰出贡献。
以及来自Bellsoft和Loongson等小型组织以及独立开发人员的贡献,他们总共贡献了Java21中8%的修复。
ApacheCommons
ApacheZooKeeper
AssertJ
BNYMCodeKatas
JUnit5
Karate
MyBatis
这些开源软件项目里面,我稍微插一句,Zookeeper出现在里面,说明它对于Java21的大力支持,能被官方点名感谢,可以变相说明它和Java长期的良好合作。
而Zookeeper在国外其实是很受欢迎的,但在国内因为生态环境的差异,并没有受到较高的重视,我建议大家可以多学点Zookeeper,这个中间件非常值得学习。
新增功能除了数以千计的性能、稳定性和安全性更新之外,Java21还提供了数十个新特性和增强,其中15个增强非常重要,足以保证它们有自己的JDK增强建议(jep),包括6个预览特性和1个孵化特性。
从这里可以看出,Java21是Java17之后另一个非常重要的版本。
我专门整理了思维导图,需要的自行在Gitee找同名目录下载即可:

正式发布的特性,都是未来需要领悟的特性,类似于Java8发布之后那些新特性一样,会逐渐成为Java未来版本的中流砥柱。
1、JEP440:RecordPatterns通过扩展模式匹配来表达更复杂、可组合的数据查询,提高Java编程语言的生产力。
这个特性是在Java19-20都是预览特性,Java21正式发布。
2、JEP441:switch增强通过允许在case标签中使用模式,扩展了switch表达式和语句的表达性和适用性。
这个特性在Java17-20都是预览特性,Java21正式发布。
3、JEP444:虚拟线程采用简单的请求一线程模式编写的服务器应用程序能够以接近最佳的硬件利用率进行扩展。
使现有使用的代码能够在最小的修改下采用虚拟线程。
使用现有的JDK工具,能够轻松进行虚拟线程的故障排除、调试和性能分析。
通过引入虚拟线程,加速应用程序开发效率,尤其适用于云环境中的应用程序,虚拟线程是一种轻量级线程,极大地减少了编写、维护和观察高吞吐量并发应用程序的工作量。
这个特性在Java19-20都是预览特性,Java21正式发布。
这是Java21版本最重要的一个改进,也是ProjectLoom项目一直推进的很重要的一环。
ProjectLoom大家可以了解下,是Java/JVM生态系统(由OpenJDK托管)中的一个较新的项目,它试图解决传统并发模型中的限制,目标是显著减少编写、维护和观察高吞吐量并发应用程序的工作量。
说白了,就是Oracle为了改进Java高并发难题推进的一个新项目。
4、JEP431:有序集合引入新的接口,用于表示按照定义好的遇见顺序进行排列的集合。每个这样的集合都有一个明确定义的第一个元素、第二个元素,依此类推,直到最后一个元素。
为访问其第一个和最后一个元素提供统一的API,并为按相反顺序处理其元素提供统一的API。
通过提供一组统一的操作,它们适用于表示具有定义好顺序的元素序列的集合类型,提高开发者的生产力。
5、JEP439:分代ZGC通过扩展ZGarbageCollector(ZGC)来维护年轻对象和老年对象的不同分代,提高应用程序的性能。
使用GenerationalZGC运行的应用程序应该享有以下好处:
较低的分配停顿风险。
较低的堆内存开销要求。
较低的垃圾回收CPU开销。
相比非分代ZGC,这些好处应该不会显著降低吞吐量。同时,非分代ZGC的关键特性应该得以保留:
暂停时间不应超过1毫秒。
支持从几百兆字节到数太字节的堆大小。
最低限度的手动配置需求。
这是另一个非常重要的改进,主要为了减少垃圾回收对应用程序的停顿时间,是一种低延迟的垃圾回收器。
ZGC实现了许多创新的技术,例如并发的垃圾回收、分代堆布局、柔性内存操作等,可以说非常适用于需要低延迟和高吞吐量的应用。
但并不是有了ZGC,你什么应用都用ZGC,在一些特定情况下它也可能会对应用程序的吞吐量产生一些小幅度的影响,所以要根据具体应用场景的需求进行评估和选择。
6、JEP452:密钥封装机制API引入密钥封装机制(KEM)的API,KEM是一种使用公钥加密的加密技术,用于保护对称密钥的安全性。
使应用程序能够使用KEM算法,例如RSAKeyEncapsulationMechanism(RSA-KEM),椭圆曲线综合加密方案(ECIES),以及国家标准与技术研究所(NIST)后量子密码标准化过程中的候选KEM算法。
使KEM在更高级的协议,如传输层安全(TLS),以及混合公钥加密(HPKE,RFC9180)等密码方案中使用。
允许安全提供者在Java代码或本地代码中实现KEM算法。
包括在RFC9180的§4.1中定义的Diffie-HellmanKEM(DHKEM)的实现。
7、JEP449:弃用并删除32位x86端口弃用Windows32位x86(x86-32)端口,并计划在未来的发布版本中删除它。
更新构建系统,在尝试为Windows32位x86(x86-32)配置构建时发出错误信息。可以通过一个新的配置选项来抑制错误信息。
在相关文档中标记该端口和相关的端口特定功能为弃用,以便将来删除。
8、JEP451:准备禁止动态加载代理当代理以动态方式加载到运行的JVM中时,发出警告。这些警告旨在为将来的发布版本做准备,该版本默认情况下禁止动态加载代理,以提高默认的完整性。在任何发布版本中,启动时加载代理的可操作性工具不会导致发出警告。
为将来的JDK发布版本做准备,默认情况下禁止在正在运行的JVM中加载代理。
重新评估可操作性(Serviceability)与完整性之间的平衡,可操作性涉及对运行中的代码进行临时更改,而完整性假定运行中的代码不会随意更改。
确保大多数工具——不需要动态加载代理的工具——不受影响。
将动态加载代理的能力与其他所谓的“超级”功能(如深层反射)保持一致。
预览孵化特性1、JEP430:字符串模板通过简化包含运行时计算值的字符串的表达,简化了Java程序的编写,增强Java编程语言的可读性、可写性和可维护性。
2、JEP443:未命名的模式和变量通过引入未命名模式,对Java语言进行增强,未命名模式可以匹配记录组件,而无需指定组件的名称或类型;
引入未命名变量,这些变量可以进行初始化但不会被使用。这两者都以下划线字符_表示。
通过省略不必要的嵌套模式,提高记录模式的可读性;
通过确定必须声明但将不会被使用的变量(例如在catch子句中),提高所有代码的可维护性。
3、JEP445:未命名类和实例主方法通过减少样板代码和仪式感,使学生能够编写他们的第一个程序,而无需理解为大型程序设计的语言特性。
4、JEP446:作用域值在线程内部和跨线程之间实现不可变数据的共享。
易用性-提供了一种编程模型,可以在线程内部和子线程之间共享数据,以简化对数据流的推理。
可理解性-从代码的语法结构中明确共享数据的生命周期。
健壮性-确保只有合法的调用方可以访问调用方共享的数据。
性能-将共享数据视为不可变的,以便允许大量线程的共享,并实现运行时优化。
在Java20中经历了一次孵化
5、JEP453:结构化并发通过引入结构化并发的API,简化并发编程。
提倡一种并发编程风格,可以消除由取消和关闭引起的常见风险,如线程泄漏和取消延迟。
改进并发代码的可观察性。
通过引入结构化并发的API,简化并发编程。它简化了错误处理和取消操作,提高了可靠性,并增强了可观察性。
在Java19-20中经历了两次孵化
6、JEP442:外部函数和内存API引入一个API,使Java程序能够与Java运行时之外的代码和数据进行交互。
通过有效地调用外部函数(即JVM之外的代码)和安全地访问外部内存(即JVM不管理的内存),该API使Java程序能够调用本地库和处理本地数据,而不会出现JNI的脆弱性和危险性。
易用性-用优秀的纯Java开发模型替代了JavaNativeInterface(JNI)。
性能-提供与JNI和等现有API相当甚至更好的性能。
通用性-提供操作不同类型的外部内存的方法(例如本地内存、持久内存和托管堆内存),以及随着时间的推移适应其他平台(例如32位x86)和其他语言编写的外部函数(例如C++、Fortran)。
安全性-允许程序对外部内存执行不安全的操作,但默认情况下提醒用户此类操作存在风险。
在Java19-20中经历了两次预览
7、JEP448:向量API引入一个API,用于表达向量计算,在支持的CPU架构上可靠地在运行时编译为最佳向量指令,从而实现比等效的标量计算更高的性能。
以下是一些显著的改变:
向向量掩码中添加了异或(xor)操作。
改进了向量洗牌的性能,特别是在重新排列向量元素和在向量之间进行转换时。
提供一个清晰简洁的API,能够清晰简洁地表达由向量操作组成的各种向量计算,这些向量计算由循环内的序列组成,并可能带有控制流程。
该API应该与特定的CPU架构无关,能够在支持向量指令的多个架构上实现。
提供在x64和AArch64架构上可靠的运行时编译和性能。
与Valhalla项目保持一致。
在Java16-20中经历了五次孵化
总结先总结下,Java21正式发布后,我的感受是,相比于Java17捆绑式的推广,Java21的改进更具有意义。
其他的正式发布的特性,虽然有必要学习,但我觉得更多是功能性的,类似于Java8的lambada表达式和stream流,依赖于熟能生巧,而且现在有AI辅助,你不会其实也能写。
另外,最近也发布了,增加了大量新特性和改进,尤其是对于虚拟线程的支持,所以和Java21算是密不可分。
后面我会单独出一篇文章讲述的版本特性。