--- title: Java 19 新特性概览 category: Java tag: - Java新特性 --- JDK 19 定于 9 月 20 日正式发布以供生产使用,非长期支持版本。不过,JDK 19 中有一些比较重要的新特性值得关注。 JDK 19 只有 7 个新特性: - [JEP 405: Record Patterns(记录模式)](https://openjdk.org/jeps/405)(预览) - [JEP 422: Linux/RISC-V Port](https://openjdk.org/jeps/422) - [JEP 424: Foreign Function & Memory API(外部函数和内存 API)](https://openjdk.org/jeps/424)(预览) - [JEP 425: Virtual Threads(虚拟线程)](https://openjdk.org/jeps/425)(预览) - [JEP 426: Vector(向量)API](https://openjdk.java.net/jeps/426)(第四次孵化) - [JEP 427: Pattern Matching for switch(switch 模式匹配)](https://openjdk.java.net/jeps/427) - [JEP 428: Structured Concurrency(结构化并发)](https://openjdk.org/jeps/428)(孵化) 这里只对 424、425、426、428 这 4 个我觉得比较重要的新特性进行详细介绍。 相关阅读:[OpenJDK Java 19 文档](https://openjdk.org/projects/jdk/19/) ## JEP 424: 外部函数和内存 API(预览) Java 程序可以通过该 API 与 Java 运行时之外的代码和数据进行互操作。通过高效地调用外部函数(即 JVM 之外的代码)和安全地访问外部内存(即不受 JVM 管理的内存),该 API 使 Java 程序能够调用本机库并处理本机数据,而不会像 JNI 那样危险和脆弱。 外部函数和内存 API 在 Java 17 中进行了第一轮孵化,由 [JEP 412](https://openjdk.java.net/jeps/412) 提出。第二轮孵化由[ JEP 419](https://openjdk.org/jeps/419) 提出并集成到了 Java 18 中,预览由 [JEP 424](https://openjdk.org/jeps/424) 提出并集成到了 Java 19 中。 在没有外部函数和内存 API 之前: - Java 通过 [`sun.misc.Unsafe`](https://hg.openjdk.java.net/jdk/jdk/file/tip/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java) 提供一些执行低级别、不安全操作的方法(如直接访问系统内存资源、自主管理内存资源等),`Unsafe` 类让 Java 语言拥有了类似 C 语言指针一样操作内存空间的能力的同时,也增加了 Java 语言的不安全性,不正确使用 `Unsafe` 类会使得程序出错的概率变大。 - Java 1.1 就已通过 Java 原生接口(JNI)支持了原生方法调用,但并不好用。JNI 实现起来过于复杂,步骤繁琐(具体的步骤可以参考这篇文章:[Guide to JNI (Java Native Interface)](https://www.baeldung.com/jni) ),不受 JVM 的语言安全机制控制,影响 Java 语言的跨平台特性。并且,JNI 的性能也不行,因为 JNI 方法调用不能从许多常见的 JIT 优化(如内联)中受益。虽然[JNA](https://github.com/java-native-access/jna)、[JNR](https://github.com/jnr/jnr-ffi)和[JavaCPP](https://github.com/bytedeco/javacpp)等框架对 JNI 进行了改进,但效果还是不太理想。 引入外部函数和内存 API 就是为了解决 Java 访问外部函数和外部内存存在的一些痛点。 Foreign Function & Memory API (FFM API) 定义了类和接口: - 分配外部内存 :`MemorySegment`、、`MemoryAddress`和`SegmentAllocator`); - 操作和访问结构化的外部内存: `MemoryLayout`, `VarHandle`; - 控制外部内存的分配和释放:`MemorySession`; - 调用外部函数:`Linker`、`FunctionDescriptor`和`SymbolLookup`。 下面是 FFM API 使用示例,这段代码获取了 C 库函数的 `radixsort` 方法句柄,然后使用它对 Java 数组中的四个字符串进行排序。 ```java // 1. 在C库路径上查找外部函数 Linker linker = Linker.nativeLinker(); SymbolLookup stdlib = linker.defaultLookup(); MethodHandle radixSort = linker.downcallHandle( stdlib.lookup("radixsort"), ...);