JDK 24即将发布,JDK 24新特性有哪些?
兄弟们,JDK 24马上要跟大家见面啦!发布的时候还有直播,这波可不能错过。今天咱就来提前扒一扒JDK 24都有哪些新特性。
一、JDK 24发布信息
JDK 24将在3月18日23:00于YouTube进行直播发布。要是你也想第一时间了解发布现场的情况,定好闹钟准时去围观就行!在等待发布的这段时间里,咱们先好好研究下JDK 24的新特性,到时候看直播也能更有底。
二、JDK 24新特性大盘点
这次JDK 24带来了24个新特性,主要涵盖语言和API增强、性能优化、安全增强以及平台和构建调整这几个方面。下面咱就详细唠唠。
(一)语言和API增强,开发更丝滑
- JEP 483:提前类加载和链接
以前JVM启动的时候,每次都要动态加载和链接类,这对于那些对启动时间要求很高的应用,像微服务、无服务器函数这些来说,简直就是个大坑。而JEP 483这个功能,会在程序第一次运行的时候,把加载和链接类的信息缓存起来,下次启动就直接用,这能大大缩短应用的启动时间,对那些短时间内频繁启动的程序来说,简直太友好了。 - JEP 484:Class-File API
以前操作字节码,大家可能会用ASM这类第三方库。现在JDK 24提供了标准的Class-File API,用它来解析、生成和转换Java类文件,不仅更方便,还能保证和JVM规范完美兼容,以后搞字节码操作就轻松多啦! - JEP 485:Stream Gatherers
这个新特性扩展了Stream API,让咱们可以自定义中间操作。比如说想实现滑动窗口统计,用它就能轻松搞定。就像下面这段代码:
List<Integer> numbers = List.of(1, 2, 3, 4, 5); List<Integer> sums = numbers.stream() .gather(Gatherers.windowSliding(2)) .map(window -> window.stream().mapToInt(i->i).sum()) .toList(); // 结果: [3, 5, 7, 9]
先定义一个包含数字的列表,然后通过gather
方法使用Gatherers.windowSliding(2)
实现滑动窗口操作,窗口大小为2,最后计算每个窗口内数字的和,得到一个新的列表。
4. JEP 487:Scoped Values(第四次预览)
在并发环境里,有时候我们需要共享一些不可变的数据。以前用线程局部变量开销比较大,现在JEP 487提供了Scoped Values,能让我们更方便地共享不可变数据,还能降低开销。看下面这段代码:
import java.lang.ScopedValue; ScopedValue<String> userName = ScopedValue.newInstance(); userName.set("Alice", () -> { System.out.println(userName.get()); });
先创建一个ScopedValue
实例userName
,然后通过set
方法设置值,在set
方法的第二个参数里,就可以获取到设置的值并打印出来。
5. JEP 488:原始类型在模式、instanceof和switch中的使用(第二次预览)
这个特性把模式匹配扩展到了原始类型,让instanceof
和switch
的功能更强大了。比如下面这样:
Object obj =...; if (obj instanceof int i) { System.out.println("It's an int: " + i); }
以前判断一个对象是不是int
类型没这么方便,现在用这个新特性,直接就能判断,还能把对象转成int
类型赋值给变量i
,用起来可太顺手了。
6. JEP 489:Vector API(第九次孵化)
搞数值计算的兄弟们有福啦!JEP 489的Vector API可以利用CPU的SIMD指令进行矢量计算,这对科学计算和机器学习这类对性能要求高的场景来说,能大大提升计算速度。看代码:
import jdk.incubator.vector.IntVector; import jdk.incubator.vector.VectorSpecies; VectorSpecies<Integer> species = IntVector.SPECIES_256; IntVector vector = IntVector.fromArray(species, array, offset); IntVector result = vector.add(vector); result.intoArray(array, offset);
先定义一个VectorSpecies
,然后根据它创建一个IntVector
,对向量进行加法操作,最后把结果存回数组。有了这个API,数值计算的效率直接起飞。
7. JEP 492:灵活构造器体(第三次预览)
以前在写构造器的时候,如果想在调用超类构造器前后添加代码,会有点麻烦。现在JEP 492让构造器更灵活了,看下面这个例子:
public class Sub extends Super { int x; { x = 10; } // 前导代码 public Sub() { super(); System.out.println(x); // 后继代码 } }
在子类的构造器里,可以在超类构造器调用之前写代码,给x
赋值;也能在超类构造器调用之后写代码,打印x
的值,是不是很方便?
8. JEP 494:模块导入声明(第二次预览)
以前导入模块里的包,得一个一个导,麻烦得很。现在JEP 494允许用一条语句导入模块的所有包,像这样:
import module com.xiaozoujishu.lib;
就这一句话,com.xiaozoujishu.lib
模块里的所有包都能导入了,代码瞬间简洁了不少。
9. JEP 495:简单源文件和实例主方法(第四次预览)
这就是个语法糖,以前写Java程序的入口方法,必须得写static void main
,现在有了JEP 495,直接写void main
就行,编译器会自动识别它是入口方法。比如:
void main() { // 自动识别为入口方法 System.out.println("Hello, Simplified Main!"); }
代码量减少了,看着也更清爽。
10. JEP 499:结构化并发(第四次预览)
并发编程里,处理错误和清理资源一直是个头疼的问题。JEP 499的结构化并发把相关任务当成一个单元来管理,能让错误处理和资源清理变得更简单,大大提高并发的可靠性。看代码:
import java.util.concurrent.StructuredTaskScope; try (var scope = new StructuredTaskScope<String>().fork(new Task1()).fork(new Task2())) { scope.join(); scope.resultStream().forEach(System.out::println); } catch (Exception e) { // 处理任务异常 }
通过StructuredTaskScope
把Task1
和Task2
这两个任务放到一个作用域里管理,join
方法等待所有任务执行完成,resultStream
可以获取任务的结果,catch
块用来处理任务执行过程中可能出现的异常。
(二)性能优化,跑得更快更稳
- JEP 404:分代Shenandoah(实验性)
Shenandoah垃圾回收器大家应该都不陌生,JDK 24给它加了分代模式。这么一改,不仅能提高程序的吞吐量,还能让程序在负载高峰的时候更稳,不容易出问题。不过目前还是实验性的,用在生产环境的时候可得悠着点。 - JEP 450:紧凑对象头(实验性)
在64位架构下,以前对象头占用的空间比较大,有96 – 128位。JEP 450把对象头的大小减少到了64位,这样就能降低内存占用,让内存的使用效率更高。同样,这也是个实验性的特性,使用的时候要谨慎。 - JEP 475:G1垃圾回收器的晚期屏障扩展
这个特性是针对G1垃圾回收器的,通过在C2编译后期扩展屏障,让G1垃圾回收器执行起来更简单,运行时间也能缩短,程序的性能自然就提升了。 - JEP 490:ZGC:移除非分代模式
JDK 24把ZGC的非分代模式去掉了,这么做主要是为了简化维护工作,让分代模式得到更广泛的应用。 - JEP 491:虚拟线程同步无锁定
在虚拟线程同步的时候,如果代码阻塞了,以前会占用平台线程,现在JEP 491让虚拟线程在同步代码阻塞时可以释放平台线程,这样程序的可扩展性就更强了。 - JEP 493:无JMOD的运行时镜像链接
以前用jlink创建运行时镜像的时候,需要JMOD文件,现在JDK 24不用了。这么一来,JDK的大小能减少大概25%,这可太香了!
(三)安全增强,抵御未来风险
- JEP 478:键派生函数API(预览)
这个API支持像HKDF和Argon2这样的密钥派生函数。比如说,我们要生成一个密钥,可以这么写:
import javax.crypto.KDF; KDF kdf = KDF.getInstance("HKDF"); SecretKey derivedKey = kdf.extractAndExpand(new SecretKeySpec(secret, "HmacSHA256"), salt, 32);
通过KDF
这个API,就能方便地生成密钥,保障数据安全。
2. JEP 496:量子抗性模块 – 格栅基密钥封装机制
这个特性提供了量子抗性密钥封装机制,能保护对称密钥。在量子计算越来越火的今天,有了这个机制,我们的数据能更好地抵御量子攻击。看代码:
KeyAgreement ka = KeyAgreement.getInstance("ML-KEM"); ka.init(kp.getPublic()); byte[] ciphertext = ka.generateSecret();
通过KeyAgreement
和ML-KEM
,就能实现密钥封装,保护对称密钥。
3. JEP 497:量子抗性模块 – 格栅基数字签名算法
它提供了量子抗性数字签名,能检测数据有没有被未经授权修改。代码示例如下:
Signature sig = Signature.getInstance("ML-DSA"); sig.initSign(privateKey); sig.update(data); byte[] signature = sig.sign();
用Signature
和ML-DSA
就能对数据进行签名,保证数据的完整性和安全性。
4. JEP 486:永久禁用安全管理器
这个特性把安全管理器给禁用了,还移除了相关的引用,这样能让平台更简洁。
(四)平台和构建调整,紧跟现代架构
- JEP 472:准备限制JNI使用
JNI在开发中用得还挺多的,但是从JDK 24开始,调用JNI_CreateJavaVM()
会触发警告,这是在为未来默认限制JNI使用做准备。以后咱们用JNI的时候可得小心点了。 - JEP 479:移除Windows 32位x86端口
现在32位系统用得越来越少了,JDK 24直接把Windows 32位的支持给移除了,这样能简化构建过程。 - JEP 501:弃用Linux 32位x86端口以移除
和Windows 32位类似,Linux 32位x86端口也被弃用了,计划在JDK 25移除,这也是为了让JDK更适配现代的64位架构。 - JEP 498:对sun.misc.Unsafe内存访问方法使用发出警告
sun.misc.Unsafe
里的内存访问方法已经不推荐使用了,在JDK 24里,用Unsafe.getInt()
这类方法会触发运行时警告,大家还是赶紧迁移到标准API吧。
三、总结
总的来说,JDK 24带来了不少让人眼前一亮的新特性,在并发编程、性能优化和安全增强等方面都有很大的改进。不过要注意,里面有很多功能还处于实验性和预览阶段,要是用到线上环境,一定要做好充分的测试,别给自己挖坑。