拓展阅读
jdk18 有哪些新特性
JDK 18 引入了一系列新特性,根据搜索结果,以下是 JDK 18 的一些主要新特性:
-
垃圾收集器的改进:可能会引入新的垃圾收集器或对现有垃圾收集器进行优化,以提高内存管理效率和减少应用程序的暂停时间。
-
安全性增强:强化安全API,包括更好的加密支持和安全协议的更新,以抵御最新的网络威胁。
- API增强和新功能:
- 标准库的增强:集合API和输入/输出API的改进。
- 并发工具:引入更高级的并发工具和改进现有工具。
- 语言特性支持:
- 记录类(Record):可能进一步增强,提供更多灵活性和功能。
- 模式匹配:进一步增强模式匹配,特别是在
switch
表达式中。
-
性能和安全性的提升:除了垃圾收集器和安全性的改进,还包括其他性能优化和安全特性。
- 新的或改进的工具和库:
- 诊断和监控工具:提供新的或改进的JVM监控和诊断工具。
- 构建和部署工具:改进Java编译器、打包工具等。
-
互联网地址解析 SPI:引入了互联网地址解析服务提供者接口(SPI),允许开发者自定义主机名和网络地址的解析方式。
-
JEP 400: 默认字符集为 UTF-8:将 UTF-8 设置为默认字符集,以减少跨平台字符编码问题。
-
JEP 408: 简易的 Web 服务器:提供了一个命令行工具来启动一个只提供静态文件的最小web服务器。
-
JEP 413: Java API 文档中的代码片段:优化了 Java API 文档中的代码片段展示。
-
JEP 416: 使用方法句柄重新实现反射核心:改进了
java.lang.reflect
包中的Method
和Constructor
的实现,提高了反射操作的性能。 -
JEP 417: Vector API:向量 API 的第三次孵化,提供了一种表达向量计算的方式,可以在运行时编译为最佳向量指令。
-
JEP 418: 互联网地址解析:定义了一个新的服务提供者接口(SPI),用于主机名和网络地址的解析。
-
JEP 419: Foreign Function & Memory API:第二次孵化,允许 Java 程序与 Java 运行时之外的代码和数据进行互操作。
-
JEP 420: Pattern Matching for switch:模式匹配在
switch
语句中的增强,提供了更丰富的模式类型和更好的类型检查。 - JEP 421: Deprecate Finalization for Removal:计划在未来版本中删除对象的 finalization 机制,因为它存在多种问题,如不可预测的延迟、不受约束的行为等。
这些特性展示了 JDK 18 在性能、安全性、语言增强、工具改进以及 API 文档等方面的进步。
JDK 18 垃圾收集器改进
在 JDK 18 中,垃圾收集器(Garbage Collector,GC)的改进主要集中在提高性能和降低延迟方面。
以下是 JDK 18 中垃圾收集器的一些关键改进:
-
G1 GC 的持续优化: G1 GC 作为 JDK 9 及以后版本的默认垃圾收集器,其设计目标是在保持高吞吐量的同时,尽可能减少垃圾收集的暂停时间。在 JDK 18 中,G1 GC 继续得到优化,以进一步提升性能。
-
低延迟 GC 的改进: ZGC 和 Shenandoah GC 作为低延迟垃圾收集器,它们在 JDK 18 中也持续得到改进。这些收集器的设计允许应用程序在垃圾收集过程中继续执行,从而减少了由于垃圾收集导致的应用程序停顿时间。
-
性能度量的改进: JDK 18 继续改进垃圾收集的性能度量,包括吞吐量、延迟和内存占用。这些度量帮助开发者了解 GC 的性能影响,并根据应用程序的具体需求选择合适的垃圾回收器。
-
NUMA 感知: G1 GC 增加了对非统一内存访问(NUMA)架构的感知,这有助于在多插槽内存的机器上优化性能。G1 GC 会尝试将对象保留在同一 NUMA 节点上,以减少内存访问延迟。
-
完整垃圾回收的改进: G1 GC 在极端情况下可能会执行完整的垃圾回收。JDK 18 改进了这一过程,使其与 Parallel GC 的完整回收性能相当,尽管这种情况仍然需要尽量避免。
-
垃圾回收元数据的优化: JDK 18 对 G1 GC 的元数据进行了优化,减少了其内存占用。通过减少所需的辅助数据结构大小,G1 GC 能够更有效地管理内存。
-
互联网地址解析 SPI: JDK 18 引入了互联网地址解析服务提供者接口(SPI),允许开发者自定义主机名和网络地址的解析方式。这可能间接影响网络应用的垃圾回收性能,因为它允许使用更高效的解析服务。
-
其他潜在改进: 随着 JDK 的不断发展,可能还包括其他未明确列出的改进,如垃圾收集算法的进一步优化、垃圾收集器的可配置性的提高、以及对特定工作负载的针对性优化等。
JDK 18 中的这些改进旨在为 Java 开发者提供更高效、更可预测的内存管理工具,帮助他们构建性能更强、延迟更低的应用程序。
开发者可以期待在 JDK 18 中获得更好的性能和更低的延迟,尤其是在使用 G1 GC 或其他低延迟收集器时。
JDK 18 互联网地址解析 SPI
JDK 18 引入了一个新的服务提供者接口(SPI),即互联网地址解析 SPI(JEP 418),这允许 java.net.InetAddress
使用除了平台内置解析器之外的解析器。
以下是互联网地址解析 SPI 的详细介绍:
- 定义和目的:
- 互联网地址解析 SPI 定义了一个新的服务提供者接口,使得
java.net.InetAddress
可以使用第三方解析器,而不是仅仅依赖于平台的内置解析器。
- 互联网地址解析 SPI 定义了一个新的服务提供者接口,使得
- 动机:
- 此 SPI 的动机包括为 Project Loom 做准备,因为当前
InetAddress
的解析操作可能会阻塞操作系统调用,这对于 Loom 的轻量级虚拟线程来说是一个问题。 - 它还旨在兼容新的网络协议,如 DNS over QUIC/TLS/HTTPS,并允许框架和应用程序更精细地控制解析结果。
- 此 SPI 的动机包括为 Project Loom 做准备,因为当前
- 使用场景:
- 允许开发者自定义解析策略,提供更灵活的控制和扩展性。
- 可以用于测试目的,例如实现自定义解析器以模拟远程请求解析到本地地址。
- 工作原理:
InetAddress
将使用服务加载器(java.util.ServiceLoader
)来查找解析器提供者。如果没有找到提供者,则使用内置的实现。- 新的接口包括
InetAddressResolverProvider
,它是一个抽象类,用于定位解析服务;InetAddressResolver
,定义了基本的前向和反向查找操作的方法;以及InetAddressResolver.LookupPolicy
,描述了解析请求的特性。
- 实现和部署:
- 开发者可以实现
InetAddressResolverProvider
接口来提供自定义解析服务,并通过服务加载器注册以供InetAddress
使用。
- 开发者可以实现
- 优势:
- 提供了前所未有的灵活性和控制能力,允许开发者根据具体的应用需求定制解析逻辑。
- 增强了安全性,通过使用更安全的解析服务,如 DNS over HTTPS,可以提高应用的安全性。
- 可能改进性能,在某些情况下,使用自定义解析器可以减少解析时间,提高应用性能。
- 测试和验证:
- JDK 18 将开发新的测试用例来验证 SPI 的工作情况,并提供概念验证解析提供者,以展示如何开发和部署优先使用的替代实现。
互联网地址解析 SPI 是 JDK 18 中一个重要的增强,它为网络地址和主机名解析提供了更多的灵活性和控制能力,使得 Java 网络编程变得更加强大和灵活。
通过这个新特性,开发者可以更好地适应不同的网络环境和需求。
JDK 18 JEP 400: 默认字符集为 UTF-8
将 UTF-8 设置为默认字符集,以减少跨平台字符编码问题。
JDK 18 引入了 JEP 400: 默认字符集为 UTF-8,这是一个重要的改进,因为它影响了 Java 程序如何处理字符编码。以下是关于 JDK 18 中 JEP 400 的详细介绍:
- 默认字符集的变更:
- 在 JDK 17 及之前的版本中,默认字符集是在 Java 虚拟机(JVM)运行时确定的,这取决于操作系统、区域设置等因素。从 JDK 18 开始,UTF-8 被指定为标准 Java API 的默认字符集。
- 目标与动机:
- 该变更的目标是使依赖于默认字符集的 Java 程序更可预测和可移植。
- UTF-8 长期以来一直是万维网上最常见的字符集,并且是许多 Java 程序处理的 XML 和 JSON 文件的标准。此外,Java 自身的 API 也越来越青睐 UTF-8,例如 NIO 接口以及属性文件。
- 兼容性与迁移:
- 此更改可能会对迁移到 JDK 18 的程序产生广泛的兼容性影响。为了缓解这个问题,JDK 18 允许通过命令行参数
java -Dfile.encoding=COMPAT
来恢复 JDK 17 及以前版本的默认字符集行为。
- 此更改可能会对迁移到 JDK 18 的程序产生广泛的兼容性影响。为了缓解这个问题,JDK 18 允许通过命令行参数
- 系统属性的变化:
- JDK 18 内部使用了与字符集相关的系统属性,如
file.encoding
和native.encoding
。特别是,file.encoding
系统属性允许在命令行上设置,以支持配置默认字符集为 UTF-8 或与 JDK 17 兼容的字符集。
- JDK 18 内部使用了与字符集相关的系统属性,如
- 源代码编码:
- Java 语言允许源代码在 UTF-16 编码中表达 Unicode 字符,这不受默认字符集选择 UTF-8 的影响。但是,
javac
编译器会受到影响,因为它假定.java
源文件是使用默认字符集编码的,除非使用(encoding)
选项另有配置。
- Java 语言允许源代码在 UTF-16 编码中表达 Unicode 字符,这不受默认字符集选择 UTF-8 的影响。但是,
- Charset.forName(“default”) 的变化:
- 在 JDK 18 中,调用
Charset.forName("default")
将引发UnsupportedCharsetException
,因为 “default” 不再是 US-ASCII 的别名,而是默认字符集的别名(UTF-8 或用户配置的字符集)。
- 在 JDK 18 中,调用
- 安全性与可维护性:
- 通过标准化默认字符集,JDK 18 简化了 Java API 的行为,减少了因字符集不一致而导致的安全风险。
- 编码问题检查:
- 开发人员在 JDK 18 或更高版本上编译代码之前,强烈建议检查字符集问题,例如通过使用
javac -encoding UTF-8 ...
命令在当前 JDK 上进行编译。
- 开发人员在 JDK 18 或更高版本上编译代码之前,强烈建议检查字符集问题,例如通过使用
JEP 400 的实施对于 Java 生态系统是一个重大的进步,它有助于减少因字符编码不一致而导致的潜在错误,并使 Java 应用程序在不同的平台和环境中行为更加一致。
JDK 18 JEP 408: 简易的 Web 服务器
提供了一个命令行工具来启动一个只提供静态文件的最小web服务器。
JDK 18 引入了 JEP 408: 简易的 Web 服务器,这是一个基于 com.sun.net.httpserver
包的最小 HTTP 服务器,用于提供单个目录层次结构的静态文件服务。以下是 JDK 18 中 JEP 408 的详细介绍:
- 命令行工具:
- 通过
jwebserver
命令行工具,可以快速启动一个简单的 Web 服务器。默认情况下,服务器会绑定到环回地址(127.0.0.1 或 ::1)和 8000 端口,并为当前工作目录提供服务。
- 通过
- API 使用:
- 除了命令行工具,JEP 408 还提供了 API,允许开发者以编程方式创建和定制 Web 服务器。这使得开发者可以更细致地控制请求的处理方式,以及如何组合和定制处理程序(HttpHandler)和过滤器(Filter)。
- 支持的请求方法:
- 简易 Web 服务器仅支持 HTTP/1.1,并且只服务于 HEAD 和 GET 请求。对于其他类型的请求,服务器将返回 501(未实现)或 405(不允许)的响应。
- 目录服务:
- 如果请求的资源是一个文件,服务器将提供该文件的内容。如果请求的资源是一个目录,并且该目录中存在索引文件,则提供索引文件的内容。否则,服务器将列出该目录下所有文件和子目录的名称,不包括符号链接和隐藏文件。
- MIME 类型:
- 服务器自动配置 MIME 类型,例如,
.html
文件将作为text/html
服务,.java
文件将作为text/plain
服务。
- 服务器自动配置 MIME 类型,例如,
- 日志输出:
- 默认情况下,每个请求都会被记录在控制台。可以通过
-o
选项改变日志输出的级别,包括none
、info
和verbose
。
- 默认情况下,每个请求都会被记录在控制台。可以通过
- 停止服务器:
- 服务器一旦启动,将一直运行,直到被外部停止。在 UNIX 平台上,可以通过向服务器发送 SIGINT 信号(例如,在终端窗口中按 Ctrl+C)来停止服务器。
- 安全性:
- 简易 Web 服务器仅适用于测试、开发和调试目的,并不提供身份验证、访问控制或加密等安全功能。因此,它不适用于生产环境。
- 命令行选项:
- 提供了多个命令行选项,如
-b
(绑定地址)、-p
(端口)、-d
(目录)、-o
(输出级别)和-version
(版本信息)等,以方便用户根据需要进行配置。
- 提供了多个命令行选项,如
JEP 408 的简易 Web 服务器为 Java 开发者提供了一个快速、简单的工具,用于本地开发和测试,尤其适合教育和原型设计。
通过命令行工具和 API,开发者可以轻松地启动和运行 Web 服务器,而无需依赖外部服务器软件。
JDK 18 JEP 413: Java API 文档中的代码片段
优化了 Java API 文档中的代码片段展示。
JDK 18 引入了 JEP 413: Java API 文档中的代码片段,这是一个旨在改进 Java API 文档中代码示例展示方式的增强特性。以下是关于 JDK 18 中 JEP 413 的详细介绍:
- 引入 @snippet 标签:
- JEP 413 为 JavaDoc 的 Standard Doclet 引入了一个新的
@snippet
标签,用于简化在 API 文档中嵌入示例源代码的过程。
- JEP 413 为 JavaDoc 的 Standard Doclet 引入了一个新的
- 代码片段的验证与样式:
- 通过
@snippet
标签,开发者可以更容易地在文档中包含有效的代码片段,并利用 JavaDoc 工具来验证这些代码片段的正确性。同时,这些代码片段可以应用现代样式,如语法高亮,并且能够自动链接到声明的名称。
- 通过
- IDE 支持:
@snippet
标签支持在 IDE 中创建和编辑代码片段,提高了开发者体验。
- 内联与外部代码片段:
@snippet
标签支持内联代码片段(直接在标签内包含代码)和外部代码片段(从单独的源文件中读取代码)。这增加了灵活性,允许开发者根据需要选择最合适的方法。
- 代码片段的元数据:
- 代码片段可以包含额外的元数据,如通过
id
属性为代码片段指定一个标识符,这可以用于在生成的 HTML 中创建链接。
- 代码片段可以包含额外的元数据,如通过
- 语言属性:
- 代码片段可以指定
lang
属性,以标识代码片段的内容类型,例如 Java 源代码或其他语言的代码。
- 代码片段可以指定
- 标记与替换:
- 代码片段中可以使用特殊的标记来指示如何展示文本,例如使用
@highlight
和@replace
标记来高亮显示代码中的特定部分或替换正则表达式匹配的文本。
- 代码片段中可以使用特殊的标记来指示如何展示文本,例如使用
- Javadoc 的改进:
@snippet
标签的引入改进了 JavaDoc 的功能,使得代码示例的展示更加直观和易于管理,同时也提高了文档的可读性和实用性。
- 代码示例的灵活性:
- 开发者可以利用
@snippet
标签的灵活性,将代码示例放置在单独的文件中,这样可以更容易地进行版本控制和代码重用。
- 开发者可以利用
- JEP 413 的目标与非目标:
- JEP 413 的目标是简化代码片段的包含和验证过程,并非使 JavaDoc 工具本身具备验证、编译或运行源代码片段的能力,这些任务留给了外部工具。
JEP 413 的实现为 Java API 文档的编写和展示带来了显著的改进,使得开发者能够更方便地创建和维护包含代码示例的文档,同时也提高了文档的质量和可读性。
JDK 18 JEP 416: 使用方法句柄重新实现反射核心
改进了 java.lang.reflect
包中的 Method
和 Constructor
的实现,提高了反射操作的性能。
JDK 18 引入了 JEP 416: 使用方法句柄重新实现反射核心,这是对 Java 反射机制的一个重要改进。以下是关于 JDK 18 中 JEP 416 的详细介绍:
- 背景和动机:
- 在 Java 18 之前,反射操作的性能并不是最优的,因为它依赖于委托模式和动态生成的字节码存根。这种实现方式虽然有效,但存在一些性能和安全性的问题。
- 方法句柄的优势:
- 方法句柄提供了一种更高效的方式来实现反射操作。它们允许开发者直接操作方法和构造函数,而不需要通过反射 API 中的代理对象。这减少了间接层和相关的性能开销。
- JEP 416 的目标:
- JEP 416 的目标是利用方法句柄重新实现
java.lang.reflect
中的Method
、Constructor
和Field
的核心功能,以提高反射操作的性能。
- JEP 416 的目标是利用方法句柄重新实现
- 实现细节:
- 通过在
java.lang.invoke
中使用方法句柄,JDK 18 对反射机制进行了底层重构,移除了对DelegatingMethodAccessorImpl
类的依赖,并减少了Unsafe
类的使用。
- 通过在
- 性能提升:
- 通过使用方法句柄,JDK 18 改进了反射操作的性能,特别是在处理大量反射调用时。新实现减少了动态字节码生成的需要,从而提高了反射调用的速度。
- 安全性和可维护性:
- 新的实现简化了反射操作的复杂性,减少了对特殊处理(如通过
MagicAccessorImpl
类)的需求,提高了代码的安全性和可维护性。
- 新的实现简化了反射操作的复杂性,减少了对特殊处理(如通过
- 兼容性:
- JEP 416 保持了与旧反射 API 的兼容性,这意味着开发者不需要修改现有的反射代码即可享受到性能提升的好处。
- 基准测试:
- OpenJDK 官方对新旧反射实现进行了基准测试,结果显示新的方法句柄基础的反射实现在某些场景下性能更优。
- 社区反馈:
- 社区对于 JEP 416 的反馈普遍积极,认为这是一个对 Java 性能有显著影响的改进,尤其是在涉及大量反射操作的高性能应用中。
JEP 416 是 JDK 18 的一个重要特性,它通过利用方法句柄改进了 Java 反射的性能和安全性,同时保持了与现有代码的兼容性。
这对于希望优化反射操作性能的开发者来说是一个重大利好。
JDK 18 JEP 417: Vector API
向量 API 的第三次孵化,提供了一种表达向量计算的方式,可以在运行时编译为最佳向量指令。
JDK 18 引入了 JEP 417: Vector API,这是对 Java 进行的一次重要增强,旨在提供对向量计算的原生支持。
以下是关于 JDK 18 中 JEP 417 的详细介绍:
- 向量计算的引入:
- JEP 417 引入了一个 API 来表达向量计算,这些计算在运行时可以编译为支持的 CPU 架构上的最佳向量指令,从而实现优于等效标量计算的性能。
- 性能提升:
- 向量计算通常可以在现代 CPU 上使用 SIMD(单指令多数据)指令执行,这可以显著提高数据处理应用程序的性能,尤其是在科学计算、图形处理和机器学习等领域。
- 跨平台的可移植性:
- Vector API 提供了一种与平台无关的方式来表达向量计算,允许开发者编写一次代码,然后在支持的 CPU 架构上都能以优化的形式运行。
- API 的孵化过程:
- Vector API 是一个孵化特性,它在 JDK 16 中首次作为孵化器模块提出(JEP 338),并在 JDK 17 中进行了第二轮孵化(JEP 414)。到了 JDK 18,Vector API 进入了第三轮孵化,这意味着它已经更加成熟和稳定。
- API 的使用:
- 开发者可以通过 Vector API 来创建和操作向量值,执行各种向量运算,如加法、减法、乘法等。API 还支持向量化的谓词和控制流结构。
- 对 JVM 的要求:
- Vector API 的实现依赖于 JVM 的支持,它需要 JVM 能够生成和执行针对目标 CPU 架构优化的向量指令。
- 社区反馈和未来展望:
- 社区对 Vector API 的反馈将影响其最终的设计和功能。随着进一步的孵化和改进,Vector API 有望在未来成为 Java 标准库中一个强大的计算工具。
- 文档和示例:
- 开发者可以查阅 OpenJDK 官方文档和相关的技术文章来了解更多关于 Vector API 的信息和使用示例。
JEP 417 的引入是 Java 语言在性能优化方面迈出的重要一步,它为 Java 程序提供了利用现代 CPU 架构的能力,以实现更高效的数据处理。
JDK 18 JEP 418: 互联网地址解析
定义了一个新的服务提供者接口(SPI),用于主机名和网络地址的解析。
JDK 18 引入了 JEP 418: 互联网地址解析 SPI,这是一个重要的改进,它定义了一个新的服务提供者接口(SPI),使得 java.net.InetAddress
可以使用除了平台内置解析器之外的解析器。
以下是关于 JDK 18 中 JEP 418 的详细介绍:
- SPI 的定义:
- JEP 418 定义了一个新的 SPI,允许开发者实现自定义的域名解析逻辑,从而提供了比平台内置解析器更高的灵活性和控制能力。
- 动机:
- 该特性的主要动机包括对 Project Loom 的支持,因为当前
InetAddress
的解析操作可能会阻塞操作系统调用,这与 Loom 的轻量级虚拟线程模型不相符。 - 它还旨在兼容新的网络协议,如 DNS over QUIC、TLS 或 HTTPS,并允许框架和应用程序更精细地控制解析结果。
- 该特性的主要动机包括对 Project Loom 的支持,因为当前
- 组件和接口:
InetAddressResolverProvider
:一个接口,用于获取InetAddressResolver
的实例。InetAddressResolver
:定义了基本的前向和反向查找操作的方法。InetAddressResolver.LookupPolicy
:描述了解析请求的特性,如请求的地址类型和返回地址的顺序。InetAddressResolverProvider.Configuration
:描述了平台的内置解析配置,提供对本地主机名和内置解析器的访问。
- 使用场景:
- 开发者可以编写任何自定义逻辑来将主机映射到其 IP 地址(以
InetAddress
的形式),反之亦然。
- 开发者可以编写任何自定义逻辑来将主机映射到其 IP 地址(以
- 正向和反向查找:
- 正向查找是指将主机名解析为 IP 地址,而反向查找是指将 IP 地址解析为主机名。
- 自定义解析器的实现:
- 开发者可以实现
InetAddressResolverProvider
接口来提供自定义解析服务,并通过服务加载器注册以供InetAddress
使用。
- 开发者可以实现
- 安全性和性能:
- 通过允许使用更安全的解析服务,如 DNS over HTTPS,可以提高应用的安全性。
- 使用自定义解析器可以减少解析时间,提高应用性能。
- JDK 的内置解析器:
- JDK 的内置解析器将继续作为默认解析器使用,除非开发者指定了自定义解析器。
- 未来展望:
- JEP 418 为 Java 网络编程提供了更多的灵活性和控制能力,随着 Java 生态系统的不断发展,可以期待未来会有更多的创新和改进。
JEP 418 的实现为 Java 网络编程带来了显著的改进,使得开发者可以更好地适应不同的网络环境和需求,提高了网络应用程序的性能和安全性。
JDK 18 JEP 419: Foreign Function & Memory API
第二次孵化,允许 Java 程序与 Java 运行时之外的代码和数据进行互操作。
JDK 18 引入了 JEP 419: Foreign Function & Memory API,这是 Project Panama 的一部分,旨在提供一个更安全、高效的方式来进行 Java 与本地代码和数据的互操作。以下是 JDK 18 中 JEP 419 的详细介绍:
- 目标与动机:
- JEP 419 的目标是提供一个 API,使得 Java 程序能够与 Java 运行时之外的代码和数据进行互操作。这包括调用本地库中的函数以及安全地访问非 JVM 管理的内存(即本地内存)。这样的设计旨在取代 JNI(Java Native Interface),因为 JNI 存在一些性能和安全性的问题。
- 主要特性:
- 内存操作:API 允许分配、操作和访问结构化的本地内存(MemorySegment, MemoryAddress, 和 SegmentAllocator)。
- 资源生命周期管理:通过 ResourceScope 控制本地资源的生命周期。
- 调用本地函数:使用 SymbolLookup, CLinker, 和 NativeSymbol 调用本地函数。
- 改进与变化:
- 相对于 JDK 17 中的孵化版本,JEP 419 进行了一些改进,包括对内存访问 var handles 的支持扩展,增加了一个更通用的反引用 API,简化了下调用(downcall)方法句柄的获取,以及引入了一个新的 API 来复制 Java 数组到内存段和从内存段复制到 Java 数组。
- 安全性:
- 该 API 旨在禁用不安全的默认操作,仅在应用程序开发者或最终用户明确选择加入后才能启用,从而提高安全性。
- 性能:
- 与 JNI 相比,JEP 419 提供了可比或更好的性能。在某些情况下,使用 FFM API 比 JNI 快四到五倍。
- 易用性:
- 与 JNI 相比,FFM API 被设计为更易于使用,预计将减少高达 90% 的 JNI 使用中的样板代码和同步工作。
- 社区反馈:
- 根据 Java 社区的反馈,JEP 419 在 JDK 18 中进行了改进,以解决第一孵化版本中的问题和不足。
- 工具支持:
- FFM API 与 jextract 工具结合使用,可以自动从 C 语言头文件生成 Java 绑定,进一步减少了使用本地库的开销。
- 未来展望:
- 随着 FFM API 的发展和成熟,预计 JNI 的使用将逐渐减少,因为 FFM API 提供了一个更安全、更高效的选择。
JEP 419 是 Project Panama 的关键组成部分,它标志着 Java 在与本地代码互操作方面的一个重要进步。
通过提供对本地内存和函数的直接操作,同时保持与 Java 平台的安全和性能特性,FFM API 为 Java 开发者提供了一个强大的工具来访问和操作本地资源。
JDK 18 JEP 420: Pattern Matching for switch
JDK 18 引入了 JEP 420: Pattern Matching for switch,这是 Java 语言中模式匹配特性的扩展,允许在 switch
表达式和语句中使用模式。以下是 JDK 18 中 JEP 420 的详细介绍:
- 目标与动机:
- JEP 420 的目标是扩展
switch
表达式和语句的表达能力,允许在case
标签中使用模式,从而提供一种更简洁、更安全的方式来处理复杂的数据导向查询。
- JEP 420 的目标是扩展
- 历史背景:
- 模式匹配最初在 Java 16 中通过 JEP 394 引入,作为
instanceof
操作符的一部分。JDK 17 通过 JEP 406 作为预览功能引入了switch
表达式和语句的模式匹配。
- 模式匹配最初在 Java 16 中通过 JEP 394 引入,作为
- 增强的类型检查:
- JEP 420 放宽了
switch
表达式选择器表达式的类型限制,允许对任何引用类型进行模式匹配,而不仅仅是数值类型、枚举类型或字符串。
- JEP 420 放宽了
- 穷尽性检查:
switch
表达式要求能够处理选择器表达式的所有可能值,即要求是穷尽的。JEP 420 引入了对封闭类(sealed class)的更精确的穷尽性检查,当switch
语句涉及封闭类时,编译器可以检查是否所有封闭类的许可子类都已被覆盖。
- 模式变量的作用域:
- 模式变量是在
switch
标签中通过模式引入的,并且在相关的switch
表达式或语句的关联部分中是可访问的。
- 模式变量是在
- 处理
null
值:- 传统上,
switch
语句和表达式在选择器表达式为null
时会抛出NullPointerException
。JEP 420 允许将null
作为case
标签的一部分,从而将null
检查集成到switch
中。
- 传统上,
- 守卫模式:
- JEP 420 引入了守卫模式(guarded patterns),允许在模式匹配逻辑中通过任意布尔表达式进行细化。例如,可以在
case
标签中使用&&
来添加额外的条件检查。
- JEP 420 引入了守卫模式(guarded patterns),允许在模式匹配逻辑中通过任意布尔表达式进行细化。例如,可以在
- 括号模式:
- 为了解决一些解析歧义,JEP 420 引入了括号模式,允许在模式周围使用括号来分组。
- 向后兼容性:
- JEP 420 确保所有现有的
switch
表达式和语句在没有任何修改的情况下继续编译和执行。
- JEP 420 确保所有现有的
- 示例:
- 通过模式匹配,可以编写更简洁的
switch
表达式,例如:static String formatterPatternSwitch(Object o) { return switch (o) { case Integer i -> String.format("int %d", i); case Long l -> String.format("long %d", l); case Double d -> String.format("double %f", d); case String s -> String.format("String %s", s); default -> o.toString(); }; }
- 通过模式匹配,可以编写更简洁的
JEP 420 是 Java 语言在模式匹配方面的重要进展,它使得 switch
语句和表达式更加强大和灵活,有助于编写更清晰、更健壮的代码。
随着 Java 语言的不断发展,模式匹配有望在未来的版本中成为正式特性。
JDK 18 JEP 421: Deprecate Finalization for Removal
JDK 18 引入了 JEP 421: Deprecate Finalization for Removal,旨在逐步淘汰 Java 中的 finalize()
方法,并为未来的 JDK 版本中移除该特性做准备。以下是 JDK 18 中 JEP 421 的详细介绍:
- 目标与动机:
- JEP 421 的目标是帮助开发者理解
finalize()
方法的潜在风险,并为将来 Java 版本中移除该特性做准备。finalize()
机制在 Java 1.0 中引入,旨在帮助避免资源泄露,但由于其存在多个严重缺陷,已经被广泛认为是不可靠且有害的。
- JEP 421 的目标是帮助开发者理解
finalize()
方法的问题:finalize()
方法存在以下主要问题:- 不可预测的延迟:无法保证在对象变得不可访问时调用其
finalize()
方法,且调用时机可能存在不可预测的延迟。 - 不受限制的行为:
finalize()
代码可以执行任何操作,包括使对象“复活”,从而避免垃圾收集。 - 未指定的线程:
finalize()
在未指定的线程上运行,无法控制其线程或顺序。 - 性能开销:存在
finalize()
的类会增加垃圾收集器(GC)的工作量,导致性能损失。 - 不可靠的执行:应用程序使用
finalize()
可能会面临间歇性和难以诊断的失败。 - 难以正确编程:正确实现
finalize()
非常困难,且容易因不当实现而导致应用程序崩溃。
- 不可预测的延迟:无法保证在对象变得不可访问时调用其
- 替代技术:
- 推荐使用更现代和可靠的资源管理技术,如
try-with-resources
语句和Cleaner
API。
- 推荐使用更现代和可靠的资源管理技术,如
- 过渡期:
- JDK 18 保留了
finalize()
的默认启用状态,但提供了一个命令行选项--finalization=disabled
来禁用finalize()
,以便开发者可以测试在没有finalize()
的情况下应用程序的行为。
- JDK 18 保留了
- 未来工作:
- 预计在 JDK 中完全移除
finalize()
将有一个较长的过渡期,以便开发者评估其系统是否依赖于finalize()
并相应地迁移代码。
- 预计在 JDK 中完全移除
- JEP 421 的实施:
- 在 JDK 18 中,所有
finalize()
方法和与finalize()
相关的标准 Java API 方法已被弃用,以准备未来的移除。
- 在 JDK 18 中,所有
- 文档和工具支持:
- 提供文档帮助开发者迁移代码,并使用如
jdeprscan
这样的工具来查找代码中的finalize()
实例。
- 提供文档帮助开发者迁移代码,并使用如
JEP 421 是 Java 语言在安全性、可靠性和性能方面向前迈出的重要一步,它鼓励开发者采用更安全和更高效的资源管理方法。
随着 finalize()
特性的最终移除,Java 将更加现代化,并且更易于正确使用。
- 拓展阅读
- jdk18 有哪些新特性
- JDK 18 垃圾收集器改进
- JDK 18 互联网地址解析 SPI
- JDK 18 JEP 400: 默认字符集为 UTF-8
- JDK 18 JEP 408: 简易的 Web 服务器
- JDK 18 JEP 413: Java API 文档中的代码片段
- JDK 18 JEP 416: 使用方法句柄重新实现反射核心
- JDK 18 JEP 417: Vector API
- JDK 18 JEP 418: 互联网地址解析
- JDK 18 JEP 419: Foreign Function & Memory API
- JDK 18 JEP 420: Pattern Matching for switch
- JDK 18 JEP 421: Deprecate Finalization for Removal