你好呀,我是歪歪。
朋友们,好消息,好消息,重磅好消息。
从今年年初就一直在喊的具有革命性、未来性、开创新纪元的 JDK 21 按照官方的时间计划表,今天终于是要正式 GA 了:
https://openjdk.org/projects/jdk/21/
GA,就是我上面框起来的“General Availability”的缩写,直译成中文,虽然是“普通可用”的意思,但是在软件行业,它就代表正式版。
如果对外发布一个 GA 版本,就意味着这个版本已经经过全面的测试,不存在任何重大的 bug,可供普通用户进行使用。
既然说到 GA 了,歪师傅也顺便给大家普及一下一般我们看到的版本号的含义。
比如我们经常会看到一些软件发布的时候都会带上 Alpha、Beta、Gamma、RC 等等这些莫名其妙的单词,它们代表什么意思呢?
- Alpha:软件或系统的内部测试版本,仅内部人员使用。一般不向外部发布,通常会有很多 Bug,除非你也是测试人员,否则不建议使用,alpha 就是 α,是希腊字母的第一位,表示最初级的版本,beta 就是 β,alpha 版就是比 beta 还早的测试版,一般都是内部测试的版本。
- Beta:公开测试版。β 是希腊字母的第二个,顾名思义,这一版本通常是在 Alpha 版本后,该版本相对于 Alpha 版已有了很大的改进,消除了严重的错误,但还是存在着一缺陷,需要经过多次测试来进一步消除。这个阶段的版本会一直加入新的功能。
- Gamma:
软件或系统接近于成熟的版本,只需要做一些小的改进就能发行。是 beta 版做过一些修改,成为正式发布的候选版本。 - RC:Release Candidate,发行候选版本。和 Beta 版最大的差别在于 Beta 阶段会一直加入新的功能,但是到了 RC 版本,几乎就不会加入新的功能了,而主要着重于除错。RC 版本是最终发放给用户的最接近正式版的版本,发行后改正 bug 就是正式版了,就是正式版之前的最后一个测试版。
- GA:General Available,正式发布的版本,这个版本就是正式的版本。在国外都是用 GA 来说明 release 版本的。比如:MySQL Community Server 5.7.21 GA 这是 MySQL Community Server 5.7 第 21 个发行稳定的版本,GA 意味着 General Available,也就是官方开始推荐广泛使用了。
- Release:这个版本通常就是所谓的“最终版本”,在前面版本的一系列测试版之后,终归会有一个正式版本,是最终交付用户使用的一个版本,该版本有时也称为标准版。一般情况下,Release 不会以单词形式出现在软件封面上,取而代之的是符号(R)。
- Stable:稳定版。在开源软件中,都有 stable 版,这个就是开源软件的最终发行版,用户可以放心大胆的用了。这一版本基于 Beta 版,已知 Bug 都被修复,一般情况下,更新比较慢。
除了上面的这些之外,我们还经常看见一个 LTS 的版本号。
LTS,Long Term Support,长期支持版,是指针对软件的某一版本,提供长时间的技术支持、安全更新和错误修复。
相对于非 LTS 版本,LTS 版本被认为是更为稳定、可靠和安全的版本。因此,在需要稳定性和安全性较高的场景中,如生产环境、企业级应用等,LTS 版本得到广泛的应用。
在 Java 领域,LTS 版本是指 Oracle 公司发布的 Java SE(Standard Edition,标准版)中,每隔一段时间发布一个长期支持版本。
自 2018 年开始,Oracle Java SE 8 、Java SE 11、Java SE 17 成为了 LTS 版本,分别提供了 3 年、 8 年、至少 3 年的支持。
你看,一个小小的 GA 里面,隐藏了这么多的小知识点,让歪师傅一不小心就铺(水)垫(了)这么长。
说会到 JDK 21 今天的 GA 版本,一共发布了 15 个新特性:
一眼望去,其中最扎眼的,也是描述最短的一个 Feature 是 444 号 Virtual Threads:
https://openjdk.org/jeps/444
可以说这个特性就是 JDK 21 这个版本中最受瞩目、最值得期待的一个特性了。
Virtual Threads,就是虚拟线程,从 JDK 19 吆喝到 JDK 20,终于在 JDK 21 现真身了。
前面我形容 JDK 21 的时候提到了一个词:开创新纪元。
值得就是它,根据官方介绍,虚拟线程的出现,确实是开启了并发编程的新纪元,轻量且高效,用更少的开销,处理更多的任务。
最重要的是看看这个:
来,翻译翻译,什么叫做“minimal change”?
minimal,就是小小的也很可爱,就是“极小的”。
change,就是变化。
官方表示,使用 java.lang.Thread API 的现有代码,只需做 极少改动(minimal change)即可启用虚拟线程。
少到你升级到 JDK 21 之后,只需要把创建线程池的地方修改为这样就能启用虚拟线程:
至于这个玩意到底有多牛逼,你可以随便在网上检索一下,已经有很多相关的文章了。
但是我还是建议你直接看官方的这个描述,这才是第一手资料出现的地方,如果让我来描述,我也只能是对于官方文章进行拙劣的翻译。
https://openjdk.org/jeps/444
除了 444 之外,也有其他的很多实用的特性。
根据官方的信息,它们把这 15 个新特性按照 JEP 的形式分为四类:核心 Java 库,Java 语言规范,HotSpot 和安全库。
https://www.infoq.com/news/2023/09/java-21-so-far/
纳入核心 Java 库的 6 个新特性分别是:
- JEP 431:序列集合
- JEP 442:外部函数和内存 API(第三次预览)
- JEP 444:虚拟线程
- JEP 446:作用域值(预览)
- JEP 448:Vector API (第六次孵化器)
- JEP 453:结构化并发(预览)
纳入 Java 语言规范的 5 个新特性分别是:
- JEP 430:字符串模板(预览)
- JEP 440:记录模式
- JEP 441:switch 模式匹配
- JEP 443:未命名模式和变量(预览)
- JEP 445:未命名类和实例主方法(预览)
纳入 HotSpot 的 3 个新特性分别是:
- JEP 439:分代 ZGC
- JEP 449:弃用 Windows 32 位 x86 移植
- JEP 451:准备禁止动态加载代理
纳入安全库的 1 个新特性是:
- JEP 452:密钥封装机制 API
其中 445 号提案,也小小的火了一把,因为它被大多数网友调侃为“卵用不大”。
因为这个提案是为了简化 Hello World 的写法。
https://openjdk.org/jeps/445
在这个提案中,作者认为我们的 Hello World 太复杂了,要写这么多代码:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
所以他提议,为了 students 和 beginner 更快更好的入门 Java,应该简化成这样,
但是这个提案也强调了:这是预览语言功能,默认禁用。
如果你要用,需要这样操作:
- 用 javac --release 21 --enable-preview Main.java 编译程序,用 java --enable-preview Main 运行程序。
- 或者,当使用源代码启动器 source code launcher,时,用 java --source 21 --enable-preview Main.java 运行程序。
对于这个功能,怎么说的?
我的评价是:这很难评。
最后,再说一下编号为 439 的提案。
https://openjdk.org/jeps/439
ZGC,大家不陌生了吧?
这个提案提到它是干啥呢?
目前的版本中,ZGC 都是不分代 GC 的。在 JDK 21 的版本中,提供了分代 GC 的功能,但是默认是关闭状态,需要通过配置打开:
而且,注意最后这句话:
In a future release we intend to make Generational ZGC the default, at which point -XX:-ZGenerational will select non-generational ZGC. In an even later release we intend to remove non-generational ZGC, at which point the ZGenerational option will become obsolete.
在未来的版本中,官方会把 ZGenerational 设为默认值,即默认打开 ZGC 的分代 GC。
在更晚的版本中,官方会考虑删除 ZGC 的不分代 GC 功能,到时候 ZGenerational 这个配置就会被一并“优化”。
说到这个 ZGC 的分代 GC,我突然想起了一个有意思的问题。
就是 2018 年,在 JDK 11 的里面,刚刚开始宣传 ZGC 的时候,就有人问:ZGC 为什么不进行分代啊?
关于这个问题,我在 R 大那里看到了一个权威的回答:
https://www.zhihu.com/question/287945354/answer/458761494
没有什么特别的原因,就是“因为分代实现起来麻烦,想先实现出比较简单可用的版本”而已。
这句话,像不像我们常常听到的:先跑起来再说?
但是人家的“跑起来再说”和我们的“跑起来再说”完全不是一个维度的东西。
至少,人家提供的“跑起来”的版本,从 2018 年跑到了 2023 年,5 年时间。
而你的“跑起来再说”可能一周后就接到了全新的、不兼容的需求。
5 年就更别想了,业务可能都被砍了,跑不起来了。(手动狗头)
既然都提到了 ZGC 了,那就顺便提一嘴 Shenandoah 吧。
根据官方的消息,最开始 JDK 21 的版本中是包含了 Shenandoah 的。
https://openjdk.org/jeps/404
但是为什么 GA 版本中没有看到它的影子呢?
可以看看官方 6 月份的这个邮件:
https://mail.openjdk.org/pipermail/jdk-dev/2023-June/007959.html
别问,问就是时间紧,任务重,申请延期。
首先描述了原因:
Given the risks identified during the review process and the lack of time available to perform the thorough review that such a large contribution of code requires
因为 Shenandoah 在审查的过程中发现了明确的风险,并且没有足够的时间来进行针对大量代码改动所需的评审。
然后画了一个新饼:
take the time to deliver the best Generational Shenandoah that we can.
Shenandoah 团队决定“尽他们所能提供最好的分代 Shenandoah”。
并给自己设置了一个新任务,将 JDK 22 作为发布目标:
We will seek to target JDK 22.
能怎么办,等着呗。
反正你发任你发,我用 Java 8!
话虽然是这么说,但是我还是希望在我短暂的职业生涯中,有幸能在生产上使用到 JDK 21,体会一下虚拟线程和 ZGC 带来的双重服务。