Java 24于2025年3月18日正式发布,这是一个非LTS版本:
Java 24正好24个JEP,是继Java 11(18个JEP)之后的新纪录,乍一看挺多,但对于大多数程序员来说,在日常编程中并不会直观地感到有特别大的变化,下面我们一起来看看:
-
JEP 404:Generational Shenandoah (Experimental )分代Shenandoan(实验特性)
-
JEP 478:Key Derivation Function API (Preview) 密钥派生函数 API(首次预览)
-
JEP 479:Remove the Windows 32-bit x86 Port 删除Windows 32位 x86端口
-
JEP 486:Permanently Disable the Security Manager 永久禁用Security Manager
-
JEP 491:Synchronize Virtual Threads without Pinning 同步虚拟线程而不固定
-
JEP 492:Flexible Constructor Bodies (Third Preview) 灵活的构造函数体(第三次预览)
-
JEP 493:Linking Run-Time Images without JMODs 链接没有JMOD的运行时图像
-
JEP 494:Module Import Declarations (Second Preview) 模块导入声明(第二次预览)
-
JEP 495:Simple Source Files and Instance Main Methods (Fourth Preview) 简单源文件和实例main方法(第四次预览)
-
JEP 496:Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism 基于模块格的抗量子的密钥封装机制
-
JEP 497:Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm 基于模块格的抗量子的数字签名算法
-
JEP 498:Warn upon Use of Memory-Access Methods in sun.misc.Unsafe 在Unsafe中使用内存访问会发出警告
-
JEP 499:Structured Concurrency (Fourth Preview) 结构化并发(第四次预览)
-
JEP 501:Deprecate the 32-bit x86 Port for Removal 弃用32位Linux x86端口以便删除
更多内容读者可自行阅读:OpenJDK Java 24文档
一、JEP 404:分代Shenandoan(实验特性)
Java 15引入了两个新的垃圾回收器——ZGC和Shenandoah,两者的暂停时间都小于10ms,不过都没有分代(新生代和老年代),带来的后果就是必须给这俩垃圾回收器分配更多的空间,而且在回收对象时需要更频繁地标记长期存在的对象。
ps:ZGC 在Java 21引入了“分代模式”。
所以为了提Shenandoah的吞吐量和内存利用率,Java 24引入了“分代模式”,Shenandoah GC的分代模式目前处于实验阶段,使用时需要增加如下参数:
-XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=generational
二、JEP 450: 压缩对象头(实验特性)
每个Java对象都有一个对象头,对象头由一个64位的Mark Word和一个32位的Class word组成,对象头在64位平台上是128位,与对象的大小无关,如果存在大量对象,那也意味着占用大量内存。
该功能就是把Mark word和Class work合并起来,并生成64位的压缩后的对象头,从而减少Java程序的CPU和内存占用率,这也是实验特性,所以用的时候也需要加上如下参数:
-XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders
三、JEP 472: 准备限制JNI的使用
JNI允许Java程序与本地方法接口(JNI)交互,但同时也会带来风险,比如JVM崩溃、不可预知的GC行为,Java 19的外部函数和内存API(FFM API)就是为了替代JNI而引入的。
四、JEP 475: G1后期屏障扩展
该功能有助于提高云原生中Java的性能,因为它可以减少JVM预热期间的CPU和内存开销。
GC 屏障包含有关应用程序内存访问的信息。JIT 编译器在早期编译阶段像任何其他节点一样扩展 GC barrier 节点。但这会导致大量的编译开销。后期 G1 GC barrier 扩展背后的想法是让 JIT 编译器尽可能晚地扩展 barrier 节点,直到必须发出机器代码的阶段。这样,GC 特有的内存访问指令就根据相关的 barrier 信息转换成机器码,这些信息在编译初期就被标记了。JDK开发人员测试的结果是,性能提升了大概10~20%。
ps:ZGC自Java 14依赖就使用了后期屏障扩展。
五、JEP 478:密钥派生函数API(首次预览)
传统公钥的加密算法越来越容易受到黑客攻击,尤其是在量子计算方面,所以Java平台需要为开发人员提供实现后量子加密算法的方法。
所以Java 24引入了这样的API,我们可以通过新类javax.crypto.KDF来实现:
void main() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {
// 1. 获取KDF
KDF hkdf = KDF.getInstance("HKDF-SHA256");
// 2. 指定派生参数
AlgorithmParameterSpec params =
HKDFParameterSpec.ofExtract()
// 2.1. 密码
.addIKM("the super secret passphrase".getBytes(StandardCharsets.UTF_8))
// 2.2. 盐值
.addSalt("the salt".getBytes(StandardCharsets.UTF_8))
// 2.3. 应用程序信息
.thenExpand("my derived key".getBytes(StandardCharsets.UTF_8), 32);
// 3. 派生一个32位的AES密钥
SecretKey key = hkdf.deriveKey("AES", params);
System.out.println("key = " + HexFormat.of().formatHex(key.getEncoded()));
}
六、JEP 479:删除Windows 32位 x86端口
在Java 21中,Windows的32位Java端口就被标记为”弃用“,所以在Java 24中正式被删除。
七、JEP 483:提前类加载和链接
Java程序的启动和预热时间比较长,尤其是在云原生中,启动需要几秒,预热可能要几分钟。
该JEP的目标就是降低Java启动和预热的时间,在准备阶段,将读取、解析、加载和链接应用程序所需的所有类保存在缓存中。当应用程序启动时,不再需要执行这些步骤,应用程序可以通过缓存直接访问加载的类和链接的类。
八、JEP 484: 类文件 API
大多数程序员仅会通过工具间接调用此API,而且永远不会直接调用,所以就不做介绍了,感兴趣的可以去官网研究下。
九、JEP 485: 流收集器(转正)
ps:可以参考Java 22对这一特性的介绍。
十、JEP 486:永久禁用Security Manager
Security Manager API 从第一个 Java 版本开始就已经存在。它旨在通过最小权限原则保护应用程序:默认情况下,代码不受信任,开发人员必须明确授予特定代码访问某些资源的权限。
在实践中,授予权限的过程非常复杂,以至于很少有应用程序真正使用安全管理器,在Java 17中就被标记为”弃用“,Java 24正式禁用。
十一、JEP 487:作用域值(第四次预览)
在 JDK 24 中再次重新预览,并作如下改进:
从
ScopedValue
类中删除了callWhere
和runWhere
方法使用一个或多个绑定范围值的唯一方法是通过
ScopedValue.Carrier.call
和ScopedValue.Carrier.run
方法。
ps:可以参考Java 21对该功能的介绍。
十二、JEP 488: 模式中的原始类型、instanceof和switch(第二次预览)
此功能最初由 JEP 455 提出,并在 JDK 23 中作为预览功能提供。
Java 24建议第二次预览它,不做任何更改。
ps:可以参考Java 23对该功能的介绍。
十三、JEP 489:向量API(第九轮孵化)
孵化挺久了,暂时可以先参考Java 16对该特性的介绍,待正式开始预览再作详解。
十四、JEP 490:ZGC:删除非分代模式
Java 21引入了ZGC垃圾回收器的"分代模式"以优化垃圾回收性能,从Java 23开始”分代模式“作为ZGC的默认模式,但是仍然可以通过参数来使用非分代模式,为了避免这两种模式同时存在,在Java 24删除ZGC的非分代模式。
十五、JEP 491:同步虚拟线程而不固定
自从 Java 21 中引入以来,当在同步块中调用阻塞代码时,虚拟线程被“固定”到其载体线程,即载体线程被阻塞,在此期间无法为任何其他虚拟线程提供服务。这可能会导致整个应用程序冻结。
从 Java 24 开始,这个问题已成为过去。在同步块中调用阻塞代码时,虚拟线程现在与载体线程分离,然后载体线程可以执行其他虚拟线程。
ps:虚拟线程可以参考这篇文章:Java 21的虚拟线程是怎么回事
十六、JEP 492:灵活的构造函数体(第三次预览)
此功能在Java 22中进行首次预览,不过标题是super(...) 之前的语句。
Java 23进行第二次预览。
Java 24进行第三次预览,并没有重大改变。
ps:可以参考Java 22对该功能的介绍。
十七、JEP 493:链接没有JMOD的运行时图像
这个好像跟我们关系不大,感兴趣的同学可以去官网研究一下。
十八、JEP 494:模块导入声明(第二次预览)
此功能在Java 23中首次预览。
在Java 24中重新预览该功能,并增加了两个功能:
允许在导入 java.se 模块时导入整个 Java SE API;
当多个导入的模块包含具有相同名称的类时,通过允许按需导入声明来隐藏模块导入声明,从而消除歧义。
如下:
import module java.base; // exports java.util with a public Date class
import module java.sql; // exports java.sql with a public Date class
import java.sql.Date; // resolve the ambiguity of the name Date
Date d = ... // Date is resolved to java.sql.Date
十九、JEP 495:简单源文件和实例main方法(第四次预览)
ps:可以参考Java 21对该功能的介绍,标题是JEP 445:未命名类和实例主要方法(第一次预览)
二十、JEP 496:基于模块格的抗量子的密钥封装机制
未来的量子计算机威胁着 RSA 和 Diffie-Hellman 等传统加密算法。使用 ML-KEM(基于模块格的密钥封装机制 - 该链接指向美国国家标准与技术研究所网站上的机制描述)应该可以安全地交换密钥,即使在量子计算机时代也是如此:
void main() throws GeneralSecurityException {
// Step 1 (Receiver): Create a ML-KEM public/private key pair:
KeyPairGenerator generator = KeyPairGenerator.getInstance("ML-KEM");
KeyPair keyPair = generator.generateKeyPair();
PublicKey receiverPublicKey = keyPair.getPublic();
PrivateKey receiverPrivateKey = keyPair.getPrivate();
// Step 2 (Sender, has the receiver's public key):
// Create a session key and encapsulate it:
KEM kem = KEM.getInstance("ML-KEM");
KEM.Encapsulator encapsulator = kem.newEncapsulator(receiverPublicKey);
KEM.Encapsulated encapsulated = encapsulator.encapsulate();
SecretKey sessionKey = encapsulated.key();
System.out.println(HexFormat.of().formatHex(sessionKey.getEncoded()));
byte[] keyEncapsulationMessage = encapsulated.encapsulation();
// Step 3 (Receiver, has the sender's key encapsulation message):
// Decapsulate the session key:
KEM kr = KEM.getInstance("ML-KEM");
KEM.Decapsulator decapsulator = kr.newDecapsulator(receiverPrivateKey);
SecretKey decapsulatedSessionKey = decapsulator.decapsulate(keyEncapsulationMessage);
System.out.println(HexFormat.of().formatHex(decapsulatedSessionKey.getEncoded()));
// Now sender and receiver can exchange messages
// using the securely transmitted session key.
// . . .
}
二十一、JEP 497:基于模块格的抗量子的数字签名算法
与上一节中描述的 ML-KEM 方法类似,ML-DSA 方法(基于模块格的数字签名算法 - 此链接也指向美国国家标准与技术研究院)也被添加到 JDK 中,该方法也是量子安全的:
import java.security.Signature;
void main() throws GeneralSecurityException {
// Step 1 (Sender): Create a ML-KEM public/private key pair:
KeyPairGenerator generator = KeyPairGenerator.getInstance("ML-DSA");
KeyPair keyPair = generator.generateKeyPair();
PublicKey senderPublicKey = keyPair.getPublic();
PrivateKey senderPrivateKey = keyPair.getPrivate();
// Step 2 (Sender): Sign a message using the private key:
byte[] message = "Roses bloom nightly.".getBytes(StandardCharsets.UTF_8);
Signature signer = Signature.getInstance("ML-DSA");
signer.initSign(senderPrivateKey);
signer.update(message);
byte[] signature = signer.sign();
// Step 3 (Receiver): Verify the message using the sender's public key:
Signature signatureVerifier = Signature.getInstance("ML-DSA");
signatureVerifier.initVerify(senderPublicKey);
signatureVerifier.update(message);
boolean verified = signatureVerifier.verify(signature);
. . .
}
二十二、JEP 498:在Unsafe中使用内存访问会发出警告
Java 1.4 中引入的 sun.misc.Unsafe
类(20 多年前)一直是直接访问工作内存(堆和本机内存,即不受垃圾回收器管理的内存)的强大但危险的工具。
由于许多库在没有这些检查的情况下使用了sun.misc.Unsafe
的方法,因此引入了两个更可靠和安全的API,即变量句柄和外部函数和内存API。在Java 23已经将sun.misc.Unsafe中的内存访问方法标记为“弃用”,在Java 24如果还用的话,JVM会发出警告。
二十三、JEP 499:结构化并发(第四次预览)
ps:可以参考Java 21对该功能的介绍。
二十四、JEP 501:弃用32位Linux x86端口以便删除
该功能弃用了 32 位 Linux x86 端口,这是 OpenJDK 中仅存的 32 位 x86 端口,并打算在后续版本中删除它。
END:更多新特性的介绍,推荐移步至👉 Java新特性学习导航(8~24 持续更新)👈