它来了,它终于来了,一起来聊聊Java17的新特性

前言

国庆的假期已经进入了尾声,趁着这个尾巴来聊一聊JDK17的新特性。上个月Java17正式发布了,这是一个LTS版本,并且Oracle宣布所有用户可以免费使用,甚至商业和生产用途。那么,我们就一起来聊聊这次更新都有哪些新的变化和特性。

密封类

密封类和接口限制了哪些类或接口可以实现或继承它。密封类在jdk15和jdk16中作为预览功能提供,现在在jdk17中正式确定下来了。

一个类是通过使用修饰符sealed来对它进行密封的。然后在 extends 或 implements 子句之后,使用关键字 permit 指定允许扩展密封类的类。


... 一些简单密封类的定义例子

密封类对其允许的扩展的子类有以下几点的约束:

1.密封类及其允许继承的子类必须在同一个模块中,如果在未命名的模块中,则属于同一包。

2.每个允许的子类必须直接扩展密封类。

3.每个允许的子类必须使用修饰符(final,sealed,non-sealed)来描述它如何传播其超类发起的密封。


switch模式匹配(预览)

使用switch表达式和语句的模式匹配以及对模式语言的扩展来增强Java编程语言。将模式匹配扩展到switch允许针对多个模式测试表达式,每个模式都有自己特定的操作,因此可以简洁安全地表达复杂的面向数据的查询。

通常我们想要将一个诸如o之类的变量与多个备选方案进行比较。java支持使用switch语句进行多路比较,并且从Java14以后支持了switch表达式,但是不幸的是,switch仍然是非常有限的。它只支持几种非常少的类型——数值类型,枚举和字符串类型,并且只能测试与常量的完全相等性。总结成一句话就是从JDK17之后switch支持Object 类型了。

下面介绍一下switch 语句和表达式的主要新特性:

1.模式匹配和空值处理


... 模式匹配和空值处理


2.switch中的模式优化


... switch中的模式优化

3.case中的模式


...


新的macOS渲染管道

Swing API 用于渲染的Java 2D API现在可以使用适用于 macOS 的新 Apple Metal 加速渲染 API。默认情况下,该功能是禁用的,可以使用-Dsun.java2d.metal=true来启用该功能。该功能需要macOS 10.14.x或更高版本 。


访问大图标的新API

JDK17中的javax.swing.filechooser.FileSystemView.getSystemIcon(File, int, int) 方法可以用于访问高质量的图标。该方法被Windows平台完全实现,其他平台上的结果可能各不相同,后续会得到增强。

FileSystemView fsv = FileSystemView.getFileSystemView(); Icon icon = fsv.getSystemIcon(new File("application.exe"), 64, 64); JLabel label = new JLabel(icon); //用于可以通过以上代码 获取application.exe 文件的高质量图标


DatagramSocket 可直接用于加入多播组

java.net.DatagramSocket 在这个版本已经更新以便用于支持加入多播组。它现在定义了joinGroup 和 leaveGroup 方法来加入和离开多播组。这项更新意味着DatagramSocket API 可以直接用于多播应用程序而无需使用旧版的java.net.MulticastSocket API 。

增强型伪随机数生成器

为伪随机数生成器(PRNG)提供了新的接口类型和实现,包括可跳转的PRNG和额外的一类可拆分PRNG算法(LXM)。

Ideal Graph Visualizer的现代化

Ideal Graph Visualizer(IGV)是一种以可视化和交互方式探索 HotSpot VM C2即时(JIT)编译器中使用的中间表示工具,已经现代化。主要包括以下几个方面的更新:

1.支持在高达JDK15(IGV底层 NetBeans平台支持的最新版本) 上运行 IGV

2.更快的基于 Maven的IGV 构建系统

3.稳定块形成、组移除和节点跟踪

4.默认过滤器中更直观的着色和节点分类

5.具有更自然默认行为的排名快速节点搜索

现代化的IGV与早期的JDK版本生成的图形部分兼容。支持图形加载和可视化等基本功能。


错误消息中的源详细信息

当JavaDoc报告输入源文件中的问题时,类似于javac诊断消息(包括符号^和行号)。另外,日志和其他的 info 消息被写入标准的错误流,让标准的输入流用于命令行选项特别请求的输出。


新API的新页面和改进的“弃用”页面

JavaDoc现在可以生成一个页面,总结最近API的变化,使用 --since命令来包含最新版本列表。-since-label命令行选项提供要在“新API”页面标题中使用的文本。在汇总弃用项目页面上,可以查看按弃用项目所在版本分组的项目。


外部函数和内存API(孵化器)

Java程序可以通过API与Java运行时之外的代码和数据进行互操作。通过有效调用外部函数(即JVM之外的代码),以及安全地访问外部内存(即不由JVM管理的内存),API使Java程序能够调用本地库和处理本地数据,而不使用JNI。


控制台字符集API

java.io.Console 中定义了新的方法用来返回控制台的字符集。返回的字符集可能和Charset.defaultCharset() 这个方法返回的不一样。


反序列化的 JDK 飞行记录器(JFR)事件

现在可以使用 JDK Flight Recorder (JFR) 监视对象的反序列化。当启用 JFR 并且 JFR 配置包括反序列化事件时,每当正在运行的程序尝试反序列化对象时,JFR 都会发出一个事件。反序列化事件名为 jfr.Deserialization,默认情况下是禁用的。反序列化事件包含序列化过滤器机制使用的信息;请参阅 ObjectInputFilter 规范。此外,如果启用了过滤器,则 JFR 事件指示过滤器是接受还是拒绝对象的反序列化。


实现特定于上下文的反序列化过滤器

上下文特定的反序列化过滤器允许应用程序通过 JVM 范围的过滤器工厂配置上下文特定的和动态选择的反序列化过滤器,该工厂被调用为每个单独的反序列化操作选择一个过滤器。


系统属性添加本机字符编码名称

引入了新的系统属性 native.encoding。此系统属性提供底层主机环境的字符编码名称。例如,通常它在 Linux 和 macOS 平台中使用 UTF-8,在 Windows (en-US) 中使用 Cp1252。


新增java.time.InstantSource接口

引入了一个新接口 java.time.InstantSource。该接口是java.time.Clock的抽象,只关注当前时刻,不涉及时区。


十六进制格式和解析实用程序

java.util.HexFormat 为原始类型和字节数组提供与十六进制之间的转换。分隔符、前缀、后缀和大写或小写的选项由返回 HexFormat 实例的工厂方法提供。


实验编译器黑洞支持

添加了对编译器黑洞的实验支持。这些对于低级基准测试很有用,以避免在关键路径上消除死代码,而不会影响基准性能。当前支持作为 CompileCommand 实现,可通过 -XX:CompileCommand=blackhole,<method> 访问,并计划最终将其升级为公共 API。 JMH 已经能够在指示/可用时自动检测和使用此功能。


HotSpot JVM中新的类层次分析实现

HotSpot JVM 中引入了新的类层次结构分析实现。它增强了对抽象和默认方法的处理,从而改进了 JIT 编译器做出的内联决策。新的实现取代了原来的实现并且默认是开启的。 为了帮助诊断与新实现相关的可能问题,可以通过指定 -XX:+UnlockDiagnosticVMOptions -XX:-UseVtableBasedCHA 命令行标志来打开原始实现。 原始实现可能会在未来版本中删除。


统一日志支持异步日志刷新

为了避免在使用统一日志的线程中出现不希望的延迟,用户现在可以请求统一日志系统以异步模式运行。这是通过传递命令行选项 -Xlog:async 来完成的。在异步日志模式下,日志站点将所有日志消息排入缓冲区。独立线程负责将它们刷新到相应的输出。中间缓冲区是有界的。缓冲区耗尽时,将丢弃排队消息。用户可以通过使用命令行选项 -XX:AsyncLogBufferSize=<bytes> 来控制中间缓冲区的大小。


支持在 Keytool -genkeypair 命令中指定签名者

-signer 和 -signerkeypass 选项已添加到 keytool 实用程序的 -genkeypair 命令中。 -signer 选项指定签名者 PrivateKeyEntry 的密钥库别名,-signerkeypass 选项指定用于保护签名者私钥的密码。这些选项允许 keytool -genkeypair 使用签名者的私钥对证书进行签名。这对于生成使用密钥协商算法作为其公钥算法的证书特别有用。


SunJCE Provider 支持使用 AES 密码的 KW 和 KWP 模式

SunJCE 提供程序已得到增强,以支持 AES 密钥包装算法 (RFC 3394) 和带填充算法的 AES 密钥包装 (RFC 5649)。在早期版本中,SunJCE 提供程序在“AESWrap”密码算法下支持 RFC 3394,该算法只能用于包装和解包密钥。通过此增强功能,添加了两种分组密码模式 KW 和 KWP,它们支持使用 AES 进行数据加密/解密和密钥包装/解包。


新的 SunPKCS11 配置属性

SunPKCS11 提供程序添加了新的提供程序配置属性以更好地控制本机资源的使用。 SunPKCS11 提供程序消耗本机资源以使用本机 PKCS11 库。为了管理和更好地控制原生资源,添加了额外的配置属性来控制清除原生引用的频率以及注销后是否销毁底层 PKCS11 Token。 SunPKCS11 提供程序配置文件的 3 个新属性是:

destroyTokenAfterLogout (boolean, 默认为 false) 如果设置为 true,当 java.security.AuthProvider.logout() 在 SunPKCS11 提供程序实例上调用时,底层 Token 对象将被销毁,资源将被释放。这实质上使得 SunPKCS11 提供程序实例在 logout() 调用后无法使用。请注意,不应将此属性设置为 true 的 PKCS11 提供程序添加到系统提供程序列表中,因为该提供程序对象在 logout() 方法调用后不可用。

cleaner.shortInterval(整数,默认为 2000,以毫秒为单位)这定义了忙期间清除本地引用的频率,即清洁线程处理队列中不再需要的本地引用以释放本地内存的频率。请注意,在 200 次尝试失败后,即在队列中找不到引用时,更清洁线程将切换到“longInterval”频率。

cleaner.longInterval(整数,默认为 60000,以毫秒为单位)这定义了在非繁忙期间检查本机引用的频率,即清洁线程检查本机引用队列的频率。请注意,如果检测到用于清洁的本机 PKCS11 引用,则清洁器线程将切换回“shortInterval”值。


具有系统属性的可配置扩展

添加了两个新的系统属性。系统属性 jdk.TLS.client.disableExtensions 用于禁用客户端中使用的 TLS 扩展。系统属性 jdk.tls.server.disableExtensions 用于禁用服务器中使用的 TLS 扩展。


参考文档:https://www.oracle.com/java/technologies/javase/17all-relnotes.html