
3 月 22 日,南京,聊聊生成式 AI 应用构建

Java 24 / JDK 24 已正式 GA。新特性如下:
404: | Generational Shenandoah (Experimental) |
450: | Compact Object Headers (Experimental) |
472: | Prepare to Restrict the Use of JNI |
475: | Late Barrier Expansion for G1 |
478: | Key Derivation Function API (Preview) |
479: | Remove the Windows 32-bit x86 Port |
483: | Ahead-of-Time Class Loading & Linking |
484: | Class-File API |
485: | Stream Gatherers |
486: | Permanently Disable the Security Manager |
487: | Scoped Values (Fourth Preview) |
488: | Primitive Types in Patterns, instanceof, and switch (Second Preview) |
489: | Vector API (Ninth Incubator) |
490: | ZGC: Remove the Non-Generational Mode |
491: | Synchronize Virtual Threads without Pinning |
492: | Flexible Constructor Bodies (Third Preview) |
493: | Linking Run-Time Images without JMODs |
494: | Module Import Declarations (Second Preview) |
495: | Simple Source Files and Instance Main Methods (Fourth Preview) |
496: | Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism |
497: | Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm |
498: | Warn upon Use of Memory-Access Methods in sun.misc.Unsafe |
499: | Structured Concurrency (Fourth Preview) |
501: | Deprecate the 32-bit x86 Port for Removal |
下面是 Java 24 部分新特性介绍
(来源:https://mp.weixin.qq.com/s/zoePSZjKW17bf0hBuJSJAg)
JEP 485: Stream Gatherers
众所周知,Stream API 操作分为生成新 Stream 的中间操作和创建结果或产生副作用的终端操作。然而,终端操作有 collect(Collector),它允许我们通过 Collector 实现来创建自定义操作。中间操作的集合仅包含 map、flatMap、filter、distinct、sorted、peek 和 sorted。这种情况一直持续到 Java 24,它引入了 Stream Gatherers。
这个新特性的关键点如下:
-
向 java.util.stream.Stream 添加了新的 gather(Gatherer) 方法。
-
新的 java.util.stream.Gatherer 接口,由四个方法组成:
-
initializer 使用 Supplier 创建初始中间状态;
-
integrator 处理元素,可选地使用中间状态,并将结果发送到流的下游。它依赖于新的Integrator函数式接口。
-
combiner 使用BinaryOperator合并状态;
-
finisher 在所有元素处理完毕后,对中间状态执行操作并将结果发送到流的下游。它使用BiConsumer。
-
-
新的 java.util.stream.Gatherers 类,提供了几种标准的 Gatherer 实现:
-
fold 类似于 reduce 操作;
-
mapConcurrent 类似于 map,利用 Virtual Threads;
-
scan 执行增量累积;
-
windowFixed 是固定窗口的标准实现;
-
windowSliding 是滑动窗口的标准实现。
-
什么是固定窗口和滑动窗口?
除了创建实现 Gatherer 的自定义类之外,Java 还提供了静态工厂方法:
-
Gatherer.of(integrator)
-
Gatherer.ofSequential(integrator)
这两种方法都有不同附加参数形式的变体,包括前面提到的函数式接口—initializer、integrator、combiner 和 finisher。
JEP 484:类文件 API
在 JDK 22 中引入了一个用于处理类文件的自定义 API。现在,随着 JDK 24 的发布,这个 API 已经最终确定!
近年来 Java 的快速发展导致字节码频繁且定期更新,标准工具如 jlink、jar 等都需要与这些字节码交互。这些工具使用 ASM 等库来实现这种交互。为了支持新的字节码版本,工具需要等待库更新——然而库又需要等待新 JDK 版本的最终实现。这种依赖链条减缓了新类文件特性的开发和采用速度。
虽然这个 API 对大多数开发者可能没有直接用处,但它对于各种框架和库——包括 Spring 和 Hibernate——这些处理字节码并使用 ASM 的工具来说至关重要。问题在于旧版本的 ASM 与较新的 JDK 版本不兼容。如果我们需要在项目中更新 JDK 版本,ASM 也必须更新——因此,我们需要更新所有依赖它的组件...几乎是所有组件。而我们只是想升级 JDK 版本而已。
让我们探索这个新 API。在实验之后,我们整理了一个简单的示例,用于读取静态常量基本字段(需要对类文件结构有基本了解):
public class ClassFileExample {
这可能出人意料地有用,因为反射会导致类初始化。有朝一日,我们可能会深入探讨这种非预期初始化的后果。
熟悉 ASM 的开发者可能会注意到,由于 Java 的新特性,特别是模式匹配,作者选择不使用访问者模式(Visitor pattern)。
JEP 483:提前类加载与链接
这一新特性旨在优化应用程序的加载时间。为实现这一目标,Java 现在支持对已加载类进行缓存。生成和使用这一缓存的过程包含三个步骤:
-
生成 AOT 配置。使用
-XX:AOTMode=record
标志运行应用程序,并通过-XX:AOTConfiguration=PATH
指定输出文件路径:java -XX:AOTMode=record -XX:AOTConfiguration=app.aotconf -jar app.jar
2. 使用配置生成缓存。将 AOT 模式更改为 create,并使用 -XX:AOTCache=PATH
标志指定缓存输出路径:
java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:AOTCache=app.aot -jar app.jar
3. 使用缓存运行应用程序。仅使用 -XX:AOTCache=PATH
标志:
java -XX:AOTCache=app.aot -jar app.jar
根据 JEP 的数据,使用 Stream API 的简单程序的加载时间从 0.031 秒减少到 0.018 秒(减少了 42%)。基于 Spring 的项目(Spring PetClinic)的加载时间从 4.486 秒降至 2.604 秒。
我还查看了最近出版的《Quarkus in Action》一书中的简单 Quarkus 应用程序(GitHub)。加载时间从 3.480 秒减少到 2.328 秒(减少了 39.67%)。
JEP 491:虚拟线程的无固定同步
这个 JEP 解决了在同步块中使用虚拟线程时平台线程被阻塞的问题。为了理解这一变更的影响,让我们首先回顾一下Project Loom,特别是虚拟线程。
当 JEP 444 引入虚拟线程时,明确指出了两种情况下虚拟线程在阻塞时不会释放其使用的平台线程:
-
阻塞发生在同步块(synchronized block)内;
-
阻塞发生在本地方法(native methods)中——无论是JNI还是外部函数(Foreign Functions)。
现在,第一种情况已经不再有效。开发者现在可以自由选择使用 synchronized 关键字或 java.util.concurrent.locks 包,使他们能够专注于任务的具体需求。
JEP 490:ZGC:移除非分代模式
Z 垃圾收集器(ZGC)曾支持两种模式:分代模式和非分代模式。由于在大多数情况下,分代 ZGC 是首选选项,开发人员决定通过禁用其中一种模式——非分代模式——来简化 ZGC 的后续支持。ZGenerational 标志现在已被弃用,如果使用该标志,将显示警告信息:
JEP 498:使用 sun.misc.Unsafe 中的内存访问方法时发出警告
如果调用了 sun.misc.Unsafe
中与内存相关的方法,将会触发警告。这些更改符合向 VarHandle
API 和外部函数与内存 API 等现代替代方案过渡的趋势。此外,这些更改也使 Java 更进一步地迈向移除 sun.misc.Unsafe
中的内存相关方法,这些方法已经被标记为“已弃用,待移除”。此次更新还鼓励库开发者迁移到新的 API。
JEP 472:准备限制 JNI 的使用
使用 Java 原生接口(JNI)和外部函数与内存(FFM)现在会触发警告:
这是限制 JNI 和 FFM 使用的第一步。未来,该类代码可能会抛出异常。
然而,这并不意味着这些功能会被移除——否则将会很讽刺,因为 FFM 刚刚在 Java 22 中发布。
采取这一步骤是为了实现“默认完整性”(Integrity by Default)策略。
这仅意味着,启用本机访问的开发者需要明确声明他们接受 JDK 中的不安全特性。
JEP 493:无 JMOD 方式链接运行时镜像
JDK 构建时引入的 --enable-linkable-runtime
选项允许 jlink
在不依赖 JDK 中的 JMOD 文件的情况下创建运行时镜像。此优化可将最终镜像大小减少 25%。
遗忘的 JMOD
尽管此更改不会直接影响开发者,但在容器环境或创建最小化运行时镜像时尤为重要。
不过,该优化默认未启用,是否采用取决于各 JDK 发行方的决定。
例如,Eclipse Temurin 已经开始使用该选项,GraalVM 也增加了对该构建方式的支持。
JEP 486:永久禁用 Security Manager
从 Java 17 开始,Java 已经着手准备禁用 java.lang.SecurityManager
,因为该类的使用率较低且维护成本较高,并已被标记为“已弃用,待移除”。现在,来看具体的更改。
-Djava.security.manager
选项(任何形式)已不再受支持,并且会导致错误,唯一的例外是 -Djava.security.manager=disallow
。
JEP 486:永久禁用 Security Manager(续)
调用 System::setSecurityManager
现在会抛出 UnsupportedOperationException
异常。
与 SecurityManager
相关的系统属性已被忽略,同时 conf/security/java.policy
文件已被移除。
其他变更主要涉及文档更新,例如删除对 SecurityManager
和 SecurityException
的相关引用。
需要注意的是,这些类和方法并未被移除,而是被降级为“空实现”——它们要么返回 null
、false
,要么直接通过调用者的请求,或者抛出 SecurityException
或 UnsupportedOperationException
。
JEP 479:移除 Windows 32 位 x86 版本
对 Windows 32 位 x86 的支持最终被取消。这简化了构建和测试基础设施,释放了不再需要的维护资源。
移除该版本的一个主要原因是它不支持虚拟线程,而只能回退到传统的内核线程。此外,Windows 10 最后一个 32 位版本的支持将在 2025 年 10 月终止。
JEP 501:弃用 32 位 x86 版本,计划移除
其他 32 位平台的命运已经确定:它们将被移除,但不会在本次发布中执行。
目前,Linux 仍然是 Java 唯一支持的 32 位平台。现在,构建 32 位版本需要添加 --enable-deprecated-ports=yes
选项:
./configure --enable-deprecated-ports=yes
不过,预计最早在 Java 25 版本中,该版本将被完全移除。
JEP 496:抗量子模块格密钥封装机制(ML-KEM)
本 JEP 以及接下来的 JEP 都专注于后量子密码学。
后量子密码学指的是:即使在量子计算机普及后仍然有效的加密算法。
根据 FIPS 203 标准,ML-KEM
密钥封装机制(Key Encapsulation Mechanism,KEM)已在 KeyPairGenerator
、KEM
、KeyFactory
API 中实现,包括 ML-KEM-512、ML-KEM-768 和 ML-KEM-1024。
现在可以这样生成密钥对:
KeyPairGenerator generator = KeyPairGenerator.getInstance("ML-KEM-1024"); KeyPair keyPair = generator.generateKeyPair();
JEP 497:抗量子模块格数字签名算法(ML-DSA)
本 JEP 旨在引入抗量子密码学中的模块格(Module-Lattice)数字签名算法(ML-DSA),以增强 Java 安全性,使其能够抵御未来量子计算机的攻击。
背景
后量子密码学(Post-Quantum Cryptography,PQC)致力于开发即使在量子计算机普及后仍然安全的加密算法。ML-DSA(Module-Lattice Digital Signature Algorithm)是 NIST 标准化的一部分,能够提供高效、安全的数字签名方案。
实现
根据 FIPS 204 标准,本 JEP 在 Java 的 KeyPairGenerator
、Signature
和 KeyFactory
API 中添加了 ML-DSA 实现,支持以下三种安全级别:
- ML-DSA-44
- ML-DSA-65
- ML-DSA-87
开发者可以使用以下代码生成 ML-DSA 签名实例:
Signature signature = Signature.getInstance("ML-DSA");
影响
-
提供符合 NIST PQC 标准的抗量子安全签名算法
-
增强 Java 在未来量子计算时代的安全性
-
适用于需要长期安全性的系统,如金融、区块链和政府应用
JEP 475:G1 垃圾收集器的延迟屏障扩展
本 JEP 主要涉及 Garbage-First(G1)垃圾收集器 的优化,不会直接影响 Java 开发者。
具体而言,该优化将 屏障(barrier) 的实现推迟到 C2 JIT 编译的后期阶段,以简化屏障逻辑,同时减少 C2 编译时间。
这一改进不仅有助于未来开发者维护 G1 GC,还能提升整体性能。
Java 24 / JDK 24 详细更新内容查看:
- https://openjdk.org/projects/jdk/24/
- https://jdk.java.net/24/
还没有评论,来说两句吧...