原文:
2023 年 3 月 21 日,Oracle 自豪地宣布 JDK 20 全面上市。此版本是第 11 th 功能版本,按六个月的发布节奏按时交付。由于持续不断的预期改进,这种级别的可预测性使开发人员能够轻松管理他们对创新的采用。
Java 提升性能、稳定性和安全性的能力,继续使其成为世界上最受欢迎的编程语言。
Oracle JDK 20 不是长期支持 (LTS) 版本,因此它只会在六个月后被 JDK 21 取代之前收到更新。
Oracle JDK 17 甲骨文 JDK 17(2021 年 9 月 14 日 发布released )是 Java 的最新 LTS 版本。
甲骨文宣布计划缩短 LTS 版本之间的时间,从三年缩短到两年,因此 JDK 21(2023 年 9 月)计划成为下一个LTS。
JDK 20 修复速率
JDK 版本随时间的变化率多年来基本保持不变,但在六个月的节奏下,交付生产就绪功能和改进的速度急剧增加。
我们不再像过去的主要版本那样每隔几年进行数万次修复并交付近百个 JEP(JDK 增强建议),而是按照更易于管理、可预测的六个月时间表在更精简的功能版本中交付增强功能。
更改的范围从重要的新功能到日常维护、错误修复和文档改进的小改进。每个更改都在针对单个问题的单个提交中表示JDK Bug系统。
JIRA 问题在其 GA 时标记为已在 Java 11 到 Java 20 中修复,15,420
由为 Oracle 工作的人完成,而 6,184由个人开发人员和为其他组织工作的开发人员贡献。
仔细研究问题并整理受让人的组织数据,得出以下组织赞助 Java 贡献开发的图表:
在 Java 20 中,标记为已修复的 2,314 个 JIRA 问题中,有 1,595 个由 Oracle 完成,而 719 是由 Java 社区的其他成员贡献的。
甲骨文感谢为阿里巴巴、亚马逊、ARM、谷歌、华为、IBM、英特尔、ISCAS、红帽、SAP 和腾讯等组织工作的开发人员做出的杰出贡献。我们也很高兴看到小型组织(如 Bellsoft 和龙芯)以及独立开发人员的贡献,他们共同贡献了 Java 20 中 7% 的修复。
我们同样感谢许多审查提议更改的经验丰富的开发人员、尝试早期访问构建并报告问题的早期采用者,以及在 OpenJDK 邮件列表上提供反馈的敬业专业人员。
Java 20 中的新功能
除了数以千计的性能、稳定性和安全更新外,Java 20 还提供了许多新功能和增强功能,其中七项改进足够重要以保证他们自己JEPs JDK 增强建议 - JEP,涵盖四个预览功能和三个孵化器功能。
一些不需要 JEP 的最重要的变化是:
有关这些功能和许多其他新功能的完整详细信息,请访问https://jdk.java.net/20/release-notes。
JEP 预览功能 完全指定并完全实现了 Java SE 平台的语言或 VM 功能;而无常。它们在 JDK Feature Releases 中可用,以允许开发人员根据实际使用情况提供反馈,然后再在未来的版本中成为永久性的。这也为工具供应商提供了在最终确定为 Java SE 标准之前致力于支持功能的机会。
许多人认为我们会接受所谓的“反应式”框架提供的异步编程风格。通过不将并发操作直接表示为线程,它确实超出了每个请求线程模型所带来的限制,但代价是巨大的——更复杂的代码更难编写、更难阅读、更难调试或配置文件,因为平台的所有层和工具都是围绕线程构建的。 Reactive 可能是人们可以用当前的 JVM 做的最好的事情,但我们的目标是做得更好,我们可以通过使线程更轻量和更具可扩展性来做到这一点,让开发人员继续使用他们已经成功使用多年的模型和工具。
今天的开发人员有三个糟糕的选择:由于未充分利用而浪费硬件,用更差的编程模型和可观察性浪费程序员的精力,或者放弃 Java。因此,Project Loom 为开发者提供了更好的选择。
Scoped Values 允许在线程内和线程间共享不可变数据。它们优于线程局部变量,尤其是在使用大量虚拟线程时,并以多种方式提供价值,包括:
- 易用性:提供了一种编程模型,可以在线程内和子线程之间共享数据,从而简化数据流的推理。
- 可理解性:使共享数据的生命周期从代码的语法结构中可见。
- 健壮性:确保调用者共享的数据只能由合法的被调用者检索。
- 性能:将共享数据视为不可变的,以便允许大量线程共享,并启用运行时优化。
JDK 20 发行说明
DTLS Resumption Uses HelloVerifyRequest Messages (JDK-8287411)
DTLS 恢复使用 HelloVerifyRequest 消息 (JDK-8287411)
security-libs/javax.net.ssl 安全库/javax.net.ssl
通过此修复,SunJSSE DTLS 实现将默认为所有握手交换 cookie,包括新握手和恢复握手,除非系统属性 jdk.tls.enableDtlsResumeCookie
为 false
。该属性仅影响用于恢复的 cookie 交换。
(D)TLS Key Exchange Named Groups (JDK-8281236)
(D)TLS 密钥交换命名组 (JDK-8281236)
security-libs/javax.net.ssl 安全库/javax.net.ssl
添加了新的 Java SE API javax.net.ssl.SSLParameters.getNamedGroups() 和 javax.net.ssl.SSLParameters.setNamedGroups() 以允许应用程序自定义在单个 TLS 或 DTLS 连接中使用的密钥交换算法的命名组。
请注意,底层提供程序可以为每个 TLS 或 DTLS 连接定义默认的命名组。应用程序还可以使用现有的 jdk.tls.namedGroups 系统属性来自定义提供者特定的默认命名组。如果不是 null ,传递给 setNamedGroups() 方法的命名组将覆盖指定 TLS 或 DTLS 连接的默认命名组。
请注意,提供者可能尚未更新以支持新的 API,在这种情况下可能会忽略已设置的命名组。 JDK SunJSSE 提供程序支持此方法。建议第三方提供商在添加对 JDK 19 或更高版本的支持时添加对这些方法的支持。
Print warning to standard error if bad java.io.tmpdir setting is detected (JDK-8290313)
如果检测到错误的 java.io.tmpdir 设置,则向标准错误打印警告 (JDK-8290313)
core-libs/java.lang 核心库/java.lang
如果定义了自定义 java.io.tmpdir 系统属性但目录不存在,则现在会在启动时将新警告打印到标准错误流。打印的警告是:
"WARNING: java.io.tmpdir directory does not exist"
Support Unicode 15.0 (JDK-8284842)
支持 Unicode 15.0 (JDK-8284842)
core-libs/java.lang 核心库/java.lang
此版本将 Unicode 版本升级到 15.0,其中包括更新版本的 Unicode 字符数据库、Unicode 标准附件 #9、#15 和 #29: java.lang.Character 类支持 Unicode 字符数据库,总共添加了 4,489 个字符149,186 个字符。这些新增内容包括 2 个新脚本,总共 161 个脚本,以及 20 个新表情符号字符和 4,193 个 CJK(中文、日语和韩语)表意文字。 java.text.Bidi 和 java.text.Normalizer 类分别支持 Unicode 标准附件 #9 和 #15。 java.util.regex 包支持基于 Unicode 标准附件 #29 的扩展字素簇。有关 Unicode 15.0 的更多详细信息,请参阅 Unicode Consortium 的发行说明。
Add GarbageCollectorMXBean for Remark and Cleanup Pause Time in G1 (JDK-8297247)
在 G1 中添加用于 Remark 和清理暂停时间的 GarbageCollectorMXBean (JDK-8297247)
hotspot/gc
一个名为“G1 Concurrent GC”的新 GarbageCollectorMXBean 已添加到 G1 垃圾收集器中。
此 GarbageCollectorMXBean 报告 Remark 和 Cleanup 垃圾收集暂停的发生和持续时间。
与 jstat -gcutil 中的“CGC”字段类似,一个完整的并发标记周期会将 bean 的收集计数器增加 2,一个用于 Remark,一个用于 Cleanup 暂停。这些暂停现在也会更新“G1 Old Gen” MemoryManagerMXBean 内存池。
New JFR Event: jdk.InitialSecurityProperty (JDK-8292177)
新的 JFR 事件:jdk.InitialSecurityProperty (JDK-8292177)
security-libs/java.security 安全库/java.security
添加了一个新的Java Flight Recorder (JFR) 事件,以在通过 java.security.Security 类加载时记录初始安全属性的详细信息。
新事件名称为 jdk.InitialSecurityProperty ,包含以下字段:
Field name | Field | Description |
---|---|---|
key | Security | Property Key 安全属性密钥 |
value | Corresponding | Security Property Value 对应的安全属性值 |
这个新的 JFR 事件默认启用。 java.security.debug=properties 系统属性现在也将初始安全属性打印到标准错误流。有了这个新事件和已经可用的 jdk.SecurityPropertyModification 事件(启用时因为默认情况下未启用),JFR 记录现在可以监视所有安全属性的初始设置和任何后续更改。
New JFR Event: jdk.SecurityProviderService (JDK-8254711)
新的 JFR 事件:jdk.SecurityProviderService (JDK-8254711)
security-libs/java.security 安全库/java.security
添加了一个新的 Java 飞行记录器 (JFR) 事件来记录 java.security.Provider.getService(String type, String algorithm) 调用的详细信息。
新事件名称为 jdk.SecurityProviderService ,包含以下字段:
Field name | Field Description |
---|---|
type | Type of Service |
algorithm | Algorithm Name |
provider | Security Provider |
默认情况下禁用此事件,可以通过 JFR 配置文件或标准 JFR 选项启用。
Provide Poly1305 Intrinsic on x86_64 platforms with AVX512 instructions (JDK-8288047)
在 x86_64 平台上提供带有 AVX512 指令的 Poly1305 Intrinsic (JDK-8288047)
security-libs/javax.crypto 安全库/javax.crypto
此功能使用 x86_64 平台上的 AVX512 指令为 SunJCE 提供商的 Poly1305 消息身份验证代码算法提供优化的内部函数。此优化在支持 x86_64 的平台上默认启用,但可以通过提供 -XX:+UnlockDiagnosticVMOptions -XX:-UsePoly1305Intrinsics 命令行选项来禁用。
Provide ChaCha20 Intrinsics on x86_64 and aarch64 Platforms (JDK-8247645)
在 x86_64 和 aarch64 平台上提供 ChaCha20 Intrinsics (JDK-8247645)
security-libs/javax.crypto 安全库/javax.crypto
此功能为 SunJCE 提供商提供的 ChaCha20 密码提供优化的内部实现。这些优化例程专为支持 AVX、AVX2 和/或 AVX512 指令集的 x86_64 芯片组以及支持高级 SIMD 指令集的 aarch64 芯片而设计。这些内在函数在支持平台上默认启用,但可以通过向 Java 提供 -XX:-UseChaCha20Intrinsics 命令行选项来禁用。控制内在函数的标志需要选项 -XX:+UnlockDiagnosticVMOptions 。
New 'jmod --compress' Command Line Option (JDK-8293499)
新的“jmod --compress”命令行选项 (JDK-8293499)
tools
jmod
工具中添加了一个新的 --compress
命令行选项,用于在创建 JMOD 存档时指定压缩级别。接受的值为 zip-[0-9]
,其中 zip-0
不提供压缩, zip-9
提供最佳压缩。默认为 zip-6
。
Javac Warns about Type Casts in Compound Assignments with Possible Lossy Conversions (JDK-8244681)
Javac 警告复合赋值中的类型转换可能有损转换 (JDK-8244681)
tools/javac
新的 lint 选项 lossy-conversions 已添加到 javac 以警告复合赋值中的类型转换可能有损转换。如果复合赋值的右侧操作数的类型与变量类型的赋值不兼容,则隐含强制转换,并且可能会发生有损转换。
可以使用 @SuppressWarnings("lossy-conversions") 抑制新警告。
Removed Features and Options 删除的功能和选项
Thread.suspend/resume Changed to Throw UnsupportedOperationException (JDK-8249627)
Thread.suspend/resume 更改为 Throw UnsupportedOperationException (JDK-8249627)
core-libs/java.lang 核心库/java.lang
此版本中删除了使用 Thread.suspend() 和 Thread.resume() 方法挂起或恢复线程的功能。方法已更改为抛出 UnsupportedOperationException 。这些方法本质上很容易死锁,并且自 JDK 1.2 (1998) 以来已被弃用。 ThreadGroup 中用于挂起或恢复一组线程的相应方法在 Java 19 中更改为抛出 UnsupportedOperationException 。
Thread.Stop Changed to Throw UnsupportedOperationException (JDK-8289610)
Thread.Stop 更改为抛出 UnsupportedOperationException (JDK-8289610)
core-libs/java.lang 核心库/java.lang
此版本中删除了使用 Thread.stop() 方法“停止”线程的功能。该方法已更改为抛出 UnsupportedOperationException 。通过使线程抛出 java.lang.ThreadDeath 来停止线程本质上是不安全的。自 JDK 1.2 (1998) 以来, stop 方法已被弃用。 ThreadGroup 中用于“停止”一组线程的相应方法在 Java 19 中更改为抛出 UnsupportedOperationException 。
作为此更改的一部分, java.lang.ThreadDeath 已被弃用并删除。
Improved Control of G1 Concurrent Refinement Threads (JDK-8137022)
改进了 G1 并发细化线程的控制 (JDK-8137022)
hotspot/gc
G1 并发细化线程的控制已被完全取代。新控制器通常分配更少的线程。它往往在细化线程活动中具有较少的尖峰。它还倾向于延迟细化,当有多个写入相同或附近的位置时,允许写入屏障进行更多过滤,从而提高屏障的效率。
有许多命令行选项用于为旧控制器提供参数值。这些与新控制器无关,不再有任何用处。它们都已经过时了;在命令行上指定它们中的任何一个都只会打印一条关于该选项已过时的警告消息。这些选项是:
-XX:-G1UseAdaptiveConcRefinement
-XX:G1ConcRefinementGreenZone=
buffer-count
-XX:G1ConcRefinementYellowZone=
buffer-count
-XX:G1ConcRefinementRedZone=
buffer-count
-XX:G1ConcRefinementThresholdStep=
buffer-count
-XX:G1ConcRefinementServiceIntervalMillis=
msec
这些选项将在未来的某个版本中完全删除。在此之后使用这些选项中的任何一个都将终止虚拟机的启动。
Remove Support for javac -source/-target/--release 7 (JDK-8173605)
删除对 javac -source/-target/--release 7 (JDK-8173605) 的支持
tools/javac
与 JEP 182:淘汰 javac -source 和 -target 选项中概述的策略一致,对 javac 的 -source
、 -target
和 --release
标志的 7/1.7 参数值的支持已被删除。
Deprecated Features and Options 弃用的功能和选项
java.net.URL Constructors Are Deprecated (JDK-8294241)
java.net.URL 构造函数已弃用 (JDK-8294241)
core-libs/java.net 核心库/java.net
java.net.URL 构造函数在此版本中已弃用。
鼓励开发人员使用 java.net.URI
来解析或构造 URL。在需要 java.net.URL
的实例来打开连接的情况下, java.net.URI
可用于构造或解析 URL 字符串,可能调用 URI::parseServerAuthority()
来验证权限组件是否可以作为基于服务器的权限进行解析,然后调用 URI::toURL()
来创建 URL
实例。
为需要使用给定自定义流处理程序构造 URL
的高级用法提供了一种新方法 URL::of(URI, URLStreamHandler)
。
有关详细信息 [2],请参阅 java.net.URL
API 文档 [1]。
Deprecate JMX Management Applets for Removal (JDK-8297794)
弃用 JMX 管理小程序以进行删除 (JDK-8297794)
core-svc/javax.management 核心-svc/javax.management
Java 管理扩展 (JMX) 管理小程序 (m-let) 功能在未来的版本中已弃用,因为它与现代应用程序无关 - javax.management.loading 中弃用的公共类是: MLet, MLetContent, PrivateMLet, MLetMBean 。
这不会影响用于本地和远程监控的 JMX 代理、Java 虚拟机的内置工具或使用 JMX 的工具。
Known Issues
java.lang.Float.floatToFloat16 and java.lang.Float.float16ToFloat May Return Different NaN Results when Optimized by the JIT Compiler (JDK-8302976, JDK-8289551, JDK-8289552)
java.lang.Float.floatToFloat16 和 java.lang.Float.float16ToFloat 在被 JIT 编译器优化时可能返回不同的 NaN 结果(JDK-8302976、JDK-8289551、JDK-8289552)
hotspot/compiler
JDK 20 引入了两种可用于与 IEEE 754 二进制 16 格式相互转换的新方法: java.lang.Float.floatToFloat16 和 java.lang.Float.float16ToFloat 。
当 JIT 编译器优化时,新方法可能会返回不同的 NaN 结果。要禁用这些方法的 JIT 编译器优化,可以使用以下命令行选项:
-XX:+UnlockDiagnosticVMOptions -XX:DisableIntrinsic=_floatToFloat16,_float16ToFloat
JDK XSLT Transformer Limitations (JDK-8290347)
JDK XSLT 转换器限制 (JDK-8290347)
xml/jaxp
使用 JDK XSLT 转换器将样式表转换为 Java 对象的应用程序可能会遇到以下异常:
“com.sun.org.apache.xalan.internal.xsltc.compiler.util.InternalError:内部 XSLTC 错误:translet 中的方法超过了 Java 虚拟机对 64 KB 方法长度的限制。这通常是由于通过样式表中非常大的模板。尝试重组样式表以使用较小的模板。”
如果 XSL 模板的大小太大,应用程序将遇到上述异常。建议将 XSL 模板拆分为更小的模板。或者,应用程序可以通过在类路径中提供第三方实现 JAR 文件来覆盖 JDK XSLT 转换器。
Other Notes
Disabled TLSECDH* Cipher Suites (JDK-8279164)
禁用 TLSECDH* 密码套件 (JDK-8279164)
TLSECDH 密码套件已默认禁用,方法是将“ECDH”添加到 java.security
配置文件中的 jdk.tls.disabledAlgorithms
安全属性。 TLSECDH 密码套件不保留前向保密性,在实践中很少使用。请注意,某些 TLSECDH* 密码套件已被禁用,因为它们使用已禁用的算法,例如 3DES 和 RC4。此操作将禁用其余部分。任何使用以“TLSECDH”开头的密码套件的尝试都将失败并显示 SSLHandshakeException
。用户可以通过从 jdk.tls.disabledAlgorithms
安全属性中删除“ECDH”来重新启用这些密码套件,但风险自负。
Disabled DTLS 1.0 (JDK-8256660)
禁用 DTLS 1.0 (JDK-8256660)
security-libs/javax.net.ssl 安全库/javax.net.ssl
通过将“DTLSv1.0”添加到 java.security 配置文件中的 jdk.tls.disabledAlgorithms 安全属性,默认情况下已禁用 DTLS 1.0。 DTLS 1.0 随着时间的推移而减弱,并且缺乏对更强大的密码套件的支持。任何使用 DTLSv1.0 的尝试都将失败并显示 SSLHandshakeException 。用户可以通过从 jdk.tls.disabledAlgorithms 安全属性中删除“DTLSv1.0”来重新启用该版本,但风险自负。
Restore Behavior of java.math.BigDecimal.movePointLeft() and movePointRight() on a Zero Argument (JDK-8289260)
在零参数上恢复 java.math.BigDecimal.movePointLeft() 和 movePointRight() 的行为 (JDK-8289260)
core-libs/java.math 核心库/java.math
当在具有负比例的目标上使用零参数调用这些方法时,它们返回的结果在数值上与目标相同,但具有不同的未缩放值和比例。
在早期版本中,它们返回具有相同未缩放值和缩放比例的结果,这违反了规范。
当目标具有非负比例或参数不为零时,行为不变。
HTTP Response Input Streams Will Throw an IOException on Interrupt (JDK-8294047)
HTTP 响应输入流将在中断时抛出 IOException (JDK-8294047)
core-libs/java.net 核心库/java.net
HTTP 响应输入流是由 ResponseSubscribers::ofInputStream 方法返回的 InputStream 实例。在此版本中, read 方法的默认实现已更改为在执行此操作的线程被中断时抛出 IOException ,而不是忽略中断。
如果调用 read 操作的线程在阻塞 read 时被中断:
- 请求将被取消, InputStream 将被关闭
- 线程中断状态将被设置为true
- 将抛出 IOException
HttpClient Default Keep Alive Time is 30 Seconds (JDK-8297030)
HttpClient 默认保持活动时间为 30 秒 (JDK-8297030)
core-libs/java.net 核心库/java.net
在此版本中, java.net.http.HttpClient 创建的 HTTP/1.1 和 HTTP/2 连接的默认空闲连接超时值已从 1200 秒减少到 30 秒。
Idle Connection Timeouts for HTTP/2 (JDK-8288717)
HTTP/2 的空闲连接超时 (JDK-8288717)
core-libs/java.net 核心库/java.net
此版本中添加了 HTTP/2 的空闲连接超时。
jdk.httpclient.keepalivetimeout 属性现在可用于配置系统范围的值(以秒为单位),用于在使用 HttpClient 时关闭 HTTP/1.1 和 HTTP/2 的空闲连接。此外,开发者还可以使用 jdk.httpclient.keepalivetimeout.h2 指定一个超时值,专门用于HTTP/2协议,而不管运行时是否指定了jdk.httpclient.keepalivetimeout。
有关当前网络属性的列表,请参阅 JDK 20 API 文档中的 java.net.http 模块和网络属性。
URL Constructors Called with Malformed Input May Throw MalformedURLException for Cases where It Was Not Thrown Previously (JDK-8293590)
使用格式错误的输入调用的 URL 构造函数可能会在以前未抛出的情况下抛出 MalformedURLException (JDK-8293590)
core-libs/java.net 核心库/java.net
提供给 java.net.URL 构造函数的输入解析在此版本中已更改为更加严格。如果使用格式错误的输入调用 URL 构造函数,则可能会在之前未抛出的情况下抛出 MalformedURLException 。
在以前的版本中,JDK 内置的 URLStreamHander 实现执行的一些解析和验证被延迟到 URL::openConnection 或 URLConnection::connect 被调用。其中一些解析和验证操作现在在 URL 构造函数中提前执行。由格式错误的 URL 引起的异常可能会延迟到连接打开或连接,现在可能会导致在 URL 构建时抛出 MalformedURLException 。
此更改仅影响委托给 JDK 内置流处理程序实现的 URL 实例。依赖自定义的第三方 URLStreamHandler 实现的应用程序应该不受影响。
可以在命令行上指定新的 JDK 特定系统属性 -Djdk.net.url.delayParsing 或 -Djdk.net.url.delayParsing=true 以恢复到以前的行为。默认情况下,该属性未设置,新行为已就位。
提供此新属性是为了向后兼容,可能会在未来的版本中删除。
Do Not Normalize File Paths to Unicode Normalization Format D on macOS (JDK-8289689)
不要在 macOS 上将文件路径规范化为 Unicode 规范化格式 D (JDK-8289689)
core-libs/java.nio 核心库/java.nio
在 macOS 上,文件名不再规范化为 Apple 的 Unicode 规范化格式 D 变体。文件名在 macOS 10.13 之前的 HFS+ 上规范化,但在 macOS 10.13 及更新版本的 APFS 上,此规范化不再生效。可以通过将系统属性“jdk.nio.path.useNormalizationFormD”设置为“true”来启用先前的行为。
FileChannel Positional Write Is Unspecified in APPEND Mode (JDK-6924219)
在 APPEND 模式下未指定 FileChannel 位置写入 (JDK-6924219)
core-libs/java.nio 核心库/java.nio
java.nio.channels.FileChannel 的规范已更新,以阐明当通道以追加模式打开时,尝试使用 FileChannel::write(ByteBuffer,long) 方法在特定位置写入的效果取决于系统。即在通道打开时,将一个 java.nio.file.StandardOpenOption.APPEND 传递给 FileChannel::open 。特别是,在某些操作系统上,字节将写入给定位置,而在其他操作系统上,给定位置将被忽略,字节将附加到文件中。
Grapheme Support in BreakIterator (JDK-8291660)
BreakIterator 中的字素支持 (JDK-8291660)
core-libs/java.text 核心库/java.text
java.text.BreakIterator 中的字符边界分析现在符合 Unicode Consortium 的标准附件 #29 中定义的扩展字素簇中断。此更改将引入有意的行为更改,因为旧的实现只是在绝大多数字符的代码点边界处中断。例如,这是一个字符串,其中包含美国国旗和一个 4 人家庭的字素。
"🇺🇸👨👩👧👦"
在新的实现中,这个字符串将被分成两个字素:
"🇺🇸", "👨👩👧👦"
而旧的实现只是在代码点边界处中断:
"🇺", "🇸", "👨", "(zwj)", "👩", "(zwj)", "👧", "(zwj)", "👦"
其中 (zwj) 表示零宽度连接器 (U+200D)。
Update Timezone Data to 2022c (JDK-8292579)
将时区数据更新为 2022c (JDK-8292579)
core-libs/java.time 核心库/java.time
此版本包含自 2022b 起的更改,这些更改将 1970 年后具有相同时间戳数据的多个区域合并到单个时区数据库中。所有时区 ID 保持不变,但合并后的时区将指向共享时区数据库。
因此,1970 年之前的数据可能与早期的 JDK 版本不兼容。受影响的区域是 Antarctica/Vostok, Asia/Brunei, Asia/Kuala_Lumpur, Atlantic/Reykjavik, Europe/Amsterdam, Europe/Copenhagen, Europe/Luxembourg, Europe/Monaco, Europe/Oslo, Europe/Stockholm, Indian/Christmas, Indian/Cocos, Indian/Kerguelen, Indian/Mahe, Indian/Reunion, Pacific/Chuuk, Pacific/Funafuti, Pacific/Majuro, Pacific/Pohnpei, Pacific/Wake, Pacific/Wallis, Arctic/Longyearbyen, Atlantic/Jan_Mayen, Iceland, Pacific/Ponape, Pacific/Truk, and Pacific/Yap
。
详情请参考2022b公告
Weaken the InflaterInputStream Specification in Order to Allow Faster Zip Implementations (JDK-8282648)
削弱 InflaterInputStream 规范以允许更快的 Zip 实现 (JDK-8282648)
core-libs/java.util.jar 核心库/java.util.jar
由 java.util.zip.InflaterInputStream 、 ZipInputStream 和 GZIPInputStream 定义的 read 方法的规范已更改为允许这些方法偏离 InputStream.read 以用于发生“短读”的情况。
“短读”是指用户提供了一个可容纳 M 字节的缓冲区但仅读取 N 字节(其中 0 < N < M)的情况。 InputStream.read 的长期规范是 N 个字节存储在用户提供的缓冲区中,偏移量 off+N 到 off+M-1 处的元素不变。
偏差允许 read 方法使用off+N到off+M-1处的元素作为临时存储。使用这些 API 的代码在将未压缩的数据读入字节数组时不能再依赖于这些元素不受影响。
IdentityHashMap's Remove and Replace Methods Use Object Identity (JDK-8178355)
IdentityHashMap 的移除和替换方法使用对象标识(JDK-8178355)
core-libs/java.util:collections 核心库/java.util:集合
IdentityHashMap
的 remove(key, value)
和 replace(key, oldValue, newValue)
实现已得到更正。在以前的版本中,使用 equals
将值参数与映射中的值进行比较。但是, IdentityHashMap
指定所有此类比较都应使用对象标识 ( ==
) 进行。这些方法的实现现在符合规范。
Support for CLDR Version 42 (JDK-8284840)
支持 CLDR 版本 42 (JDK-8284840)
core-libs/java.util:i18n 核心库/java.util:i18n
基于Unicode Consortium 的CLDR 的Locale 数据已经升级到42 版本。详细的locale 数据变更请参考Unicode Consortium 的CLDR 发行说明。上游中可能影响格式化的一些显着变化是:
- NBSP/NNBSP prefixed to AM/PM in time format, instead of a normal space
NBSP/NNBSP 以时间格式作为 AM/PM 的前缀,而不是正常的空格 - " at " is no longer used for standard date/time format
“ at ”不再用于标准日期/时间格式 - Fix first day of week info for China (CN)
修复中国 (CN) 的一周第一天信息 - Japanese: Support numbers up to 9999京
日语:支持号码最大为 9999京
Introduce LDAP and RMI Protocol Specific Object Factory Filters to JNDI Implementation (JDK-8290368)
将 LDAP 和 RMI 协议特定对象工厂过滤器引入 JNDI 实现 (JDK-8290368)
core-libs/javax.naming 核心库/javax.naming
在此版本中,引入了新的系统和安全属性,以允许对允许从 JNDI/LDAP 和 JNDI/RMI 上下文重建 Java 对象的 JNDI 对象工厂集进行更精细的控制:
- 新的
jdk.jndi.ldap.object.factoriesFilter
属性指定允许哪些对象工厂类从 JNDI/LDAP 上下文返回的对象引用中实例化 Java 对象。它的默认值只允许在java.naming
模块中定义的对象工厂。 - 新的
jdk.jndi.rmi.object.factoriesFilter
属性指定允许哪些对象工厂类从 JNDI/RMI 上下文返回的对象引用中实例化 Java 对象。它的默认值只允许在jdk.rmi
模块中定义的对象工厂。
这些新的工厂过滤器属性通过确定是否允许特定对象工厂为 JNDI 中使用的 LDAP 或 RMI 协议实例化对象来补充 jdk.jndi.object.factoriesFilter
全局工厂过滤器属性。
依赖自定义对象工厂从 JNDI/LDAP 或 JNDI/RMI 上下文重新创建 Java 对象的应用程序将需要提供具有更新值的安全或系统属性,以允许此类第三方对象工厂重建 LDAP 或 RMI 对象。如果拒绝使用工厂,查找操作可能会导致返回 javax.naming.Reference
实例的普通实例,这可能会导致在应用程序中抛出 ClassCastException
。
有关详细信息,请参阅 java.naming 和 jdk.naming.rmi 模块信息文档。
Update Default Value and Extend the Scope of com.sun.jndi.ldap.object.trustSerialData System Property (JDK-8290367)
更新默认值并扩展 com.sun.jndi.ldap.object.trustSerialData 系统属性的范围 (JDK-8290367)
core-libs/javax.naming 核心库/javax.naming
在此版本中,默认情况下,LDAP 提供程序的 JDK 实现不再支持 Java 对象的反序列化:
- com.sun.jndi.ldap.object.trustSerialData 系统属性的默认值已更新为 false 。
- com.sun.jndi.ldap.object.trustSerialData 系统属性的范围已扩展到涵盖从 javaRemoteLocation LDAP 属性重建 RMI 远程对象。
来自 LDAP 上下文的 Java 对象的透明反序列化现在需要明确的选择加入。依赖于从 LDAP 属性重建 Java 对象或 RMI 存根的应用程序需要将 com.sun.jndi.ldap.object.trustSerialData 系统属性设置为 true 。
com.sun.jdi.ObjectReference::setValue Specification Should Prohibit Any Final Field Modification (JDK-8280798)
com.sun.jdi.ObjectReference::setValue 规范应禁止任何最终字段修改 (JDK-8280798)
core-svc/debugger
Java 调试接口 (JDI) 方法 ObjectReference.setValue
的规范在此版本中已更改为要求给定字段为非最终字段。该方法之前被指定要求静态字段是非最终的,但对最终实例字段保持沉默。 JDK 的 JDI 实现不允许使用此方法更改最终实例字段,因此此更改不会影响使用 JDK 的 JDI 实现的调试器或工具。 JDI 实现的维护者应该注意这一变化,以便他们可以使他们的实现与更新的规范保持一致。
JMX Connections Use an ObjectInputFilter by Default (JDK-8283093)
JMX 连接默认使用 ObjectInputFilter (JDK-8283093)
默认的 JMX 代理现在在 RMI 连接上设置一个 ObjectInputFilter 以限制服务器将反序列化的类型。这应该不会影响 JDK 中 MBean 的正常使用。在 Platform MBeanServer 中注册自己的 MBean 的应用程序可能需要扩展过滤器以支持其 MBean 接受作为参数的任何其他类型。默认过滤器已经涵盖了 OpenMBeans 和 MXBeans 可能使用的任何类型。
使用属性 com.sun.management.jmxremote.serial.filter.pattern 在 JDK/conf/management/management.properties 中设置过滤器模式。如果需要传递其他 Java 类型,则可以通过运行 -Dcom.sun.management.jmxremote.serial.filter.pattern= 来覆盖默认值。
序列化过滤和过滤模式格式在核心库指南中有详细描述。
G1: Disable Preventive GCs by Default (JDK-8293861)
G1:默认禁用预防性 GC (JDK-8293861)
hotspot/gc
在 JDK 17 中,G1 添加了“预防性”垃圾回收 (GC)。这些是推测性垃圾收集,目的是避免在堆快满时由于分配突发而导致代价高昂的疏散失败。
然而,这些推测性收集会带来额外的垃圾收集工作,因为对象老化是基于 GC 的数量,额外的 GC 会导致过早提升到老年代,这会导致老年代中有更多数据,并且需要更多垃圾收集工作删除这些对象。当前预测触发预防性垃圾收集非常保守,这使情况更加复杂;这意味着这些垃圾回收通常是在不必要的情况下触发的。
在大多数情况下,此功能是一个净损失,并且由于疏散失败现在处理得更快,因此不再有任何理由使用此功能并且默认情况下已禁用它,可能会被 -XX:+UnlockDiagnosticVMOptions -XX:+G1UsePreventiveGC 重新启用。
appendToClassPathForInstrumentation Must Be Used in a Thread-Safe Manner (JDK-8296472)
必须以线程安全的方式使用 appendToClassPathForInstrumentation (JDK-8296472)
hotspot/jvmti
当使用 Java 代理(例如 -javaagent:myagent.jar )和自定义系统类加载器(例如 -Djava.system.class.loader=MyClassLoader )运行应用程序时,Java 代理调用 Instrumentation.appendToSystemClassLoaderSearch API 以附加到类加载器搜索,然后自定义系统类loader appendToClassPathForInstrumentation 方法将被调用以将 JAR 文件添加到自定义系统类加载器的搜索路径。
JVM 在调用 appendToClassPathForInstrumentation 时不再在自定义类加载器上同步。自定义类加载器中的 appendToClassPathForInstrumentation 方法必须以线程安全的方式添加到类搜索路径中。
GetLocalXXX/SetLocalXXX Specification Should Require Suspending Target Thread (JDK-8288387)
GetLocalXXX/SetLocalXXX 规范应该要求暂停目标线程 (JDK-8288387)
hotspot/jvmti
GetLocalXXX/SetLocalXXX 函数的 JVM TI 规范已更改为要求目标线程挂起或当前线程。如果不满足此要求,将返回错误代码 JVMTI_ERROR_THREAD_NOT_SUSPENDED。如果目标线程不是当前线程,则需要更新使用 GetLocalXXX/SetLocalXXX API 的 JVM TI 代理以挂起目标线程。受影响的 JVM TI 函数的完整列表是:
- GetLocalObject, GetLocalInt, GetLocalLong, GetLocalFloat, GetLocalDouble, GetLocalInstance,
- SetLocalObject, SetLocalInt, SetLocalLong, SetLocalFloat, SetLocalDouble
The JNI Specification Omits an Update to the JNI Version (JDK-8290482)
JNI 规范省略了对 JNI 版本的更新 (JDK-8290482)
hotspot/runtime
此错误更新了与 DestroyJavaVM 函数相关的 JNI 规范。作为这项工作的一部分,JNI 规范版本号增加了。对 JNI 规范版本的更改也应该反映在 GetVersion 函数中,但没有。 Java SE 20 及更高版本的 GetVersion 函数已更新为 JNI_VERSION_20 。
这个新版本也在 jni.h 中记录为:
#define JNI_VERSION_20 0x00140000
Deprecate and Disable Legacy Parallel Class Loading Workaround for Non-Parallel-Capable Class Loaders (JDK-8295673)
弃用和禁用不支持并行的类加载器的遗留并行类加载解决方法 (JDK-8295673)
hotspot/runtime
一些用户定义的较旧的类加载器会通过在加载过程中释放类加载器锁来解决死锁问题。为了防止这些加载器在通过并行线程加载同一类时遇到“java.lang.LinkageError:尝试重复类定义”,HotSpot 虚拟机在 JDK 6 中引入了一种变通方法,该方法序列化加载尝试,导致后续尝试等待对于第一个完成。
当引入具有并行能力的类加载器时,类加载器以这种方式工作的需要在 JDK 7 中被删除,但变通方法保留在 VM 中。该解决方法最终被删除,并且作为第一步已被默认弃用和禁用。如果您开始看到“java.lang.LinkageError: attempted duplicate class definition”,那么您可能有一个受影响的旧类加载器。 -XX:+EnableWaitForParallelLoad 标志可用于临时恢复此版本 JDK 中的旧行为,但遗留类加载器将需要为将来的版本更新。
有关更多背景和详细信息,请参阅 CSR 请求 (JDK-8295848)。
Added Constructors (String, Throwable) and (Throwable) to InvalidParameterException (JDK-8296226)
添加构造函数 (String, Throwable) 和 (Throwable) 到 InvalidParameterException (JDK-8296226)
security-libs/java.security 安全库/java.security
构造函数 InvalidParameterException(String, Throwable) 和 InvalidParameterException(Throwable) 已添加到 java.security.InvalidParameterException 类以支持轻松构造带有原因的 InvalidParameterException 对象。
Throw Error If Default java.security File Fails to Load (JDK-8155246)
如果默认 java.security 文件加载失败抛出错误 (JDK-8155246)
security-libs/java.security 安全库/java.security
在默认 conf/security/java.security 安全配置文件加载失败的情况下,行为发生了变化。在这种情况下,JDK 现在将抛出一个 InternalError 。
这种情况永远不应该发生。默认安全文件应始终存在。在此更改之前,加载了静态安全配置。
Remove Thread Text from Subject.current (JDK-8297276)
从 Subject.current 中删除线程文本 (JDK-8297276)
security-libs/javax.security 安全库/javax.security
Subject.current 的规范在此版本中已更改,以放弃在创建线程时继承 Subject 的期望。此时 Subject 存放在 AccessControlContext 中,在创建平台线程时继承。虚拟线程不会在线程创建时捕获调用者上下文,并且不会继承 AccessControlContext 。在删除对 SecurityManager 和继承的 AccessControlContext 的支持之前,将在未来的版本中重新检查继承。
New Implementation Note for LoginModule on Removing Null from a Principals or Credentials Set (JDK-8282730)
LoginModule 关于从主体或凭据集中删除空值的新实施说明 (JDK-8282730)
在 JAAS Subject 中保存主体和凭据的 Set 实现禁止空元素,任何添加、查询或删除空元素的尝试都将导致 NullPointerException 。当尝试在注销阶段从主题中删除主体或凭据但由于先前登录失败而它们为空时,这一点尤其重要。已修复各种 JDK LoginModule 实现以避免异常。 LoginModule 接口的 logout() 方法中也添加了一个实施说明。开发人员应验证并在必要时更新任何自定义 LoginModule 实现以符合此实现建议。
An Exhaustive Switch over an Enum Class Should Throw MatchException
Rather Than IncompatibleClassChangeError
If No Switch Label Applies at Runtime (JDK-8297118)
如果在运行时没有应用切换标签,枚举类的彻底切换应该抛出 MatchException 而不是 IncompatibleClassChangeError (JDK-8297118)
tools/javac
在此版本中,当使用 --enable-preview 启用预览功能时,如果选择器表达式产生意外的枚举常量值,枚举类型上的 switch 表达式将抛出 MatchException 而不是 IncompatibleClassChangeError 。只有在编译 switch 之后通过添加新的枚举常量更改了枚举类时才会发生这种情况。
需要进行此更改以统一对通过使用模式标签增强 switch 引入的错误详尽开关的处理。
Improved Preview API Page (JDK-8287597)
改进的预览 API 页面 (JDK-8287597)
tools/javadoc(tool) 工具/javadoc(工具)
JavaDoc 生成的文档中的预览 API 页面现在提供了有关预览功能所属的 JEP 的详细信息。
Generalize see and link Tags for User-Defined Anchors (JDK-8200337)
概括用户定义锚点的查看和链接标签 (JDK-8200337)
tools/javadoc(tool) 工具/javadoc(工具)
{@link}
、 {@linkplain}
和 @see
标记已得到增强,以允许链接到 JavaDoc 为元素生成的文档中的任意锚点。为了将这些引用与成员引用区分开来,使用双散列标记 ( ##
) 将元素名称与 URI 片段分开。
Auto-Generated IDs in JavaDoc Headings (JDK-8289332)
JavaDoc 标题中自动生成的 ID (JDK-8289332)
tools/javadoc(tool) 工具/javadoc(工具)
JavaDoc 现在为文档注释中的所有 HTML 标题生成 id 属性,可用作链接锚点。