概述
Java 24 于 2025 年 3 月发布,该版本提供24项新特性(含10项孵化/预览/实验功能)
JEP 404: 分代 Shenandoah(实验性)
::: info JEP 404: Generational Shenandoah (Experimental) Enhance the Shenandoah garbage collector with experimental generational collection capabilities to improve sustainable throughput, load-spike resilience, and memory utilization. :::
通过实验性分代收集功能增强 Shenandoah 垃圾回收器,以提高可持续吞吐量、负载峰值弹性和内存利用率。
核心目标
在保持Shenandoah原有的低暂停时间优势基础上,进一步减少内存占用和CPU开销。
工作原理
将堆内存划分为年轻代和老年代,优先且更频繁地收集年轻代(通常包含大量短生命周期对象),避免其过早晋升到老年代,减少全局垃圾回收的需要。
- 新生代专用回收策略:采用复制篡法快速回收短生命周期对象,减少老年代扫描频率
- 卡表 (Card Table) 优化:精确记录老年代到新生代的跨代引用,降低 GC 停顿时间 30 %以上
- 井行标记增强:在并发标记阶段优先处理新生代区域,使平均 GC 暂停时间控制在 2ms 以内。实测表明,在 16GB 堆内存的微服务场景下,分代 Shenandoah 相比原版吞吐量提升 40 %,同时保持亚毫秒级的最大暂停时间,成为低延迟应用的理想选择。
启用方式
需添加JVM参数:
-XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=generational
适用场景
- 低延迟高响应应用:例如实时交易系统、交互式数据分析平台。
- 大量短生命周期对象:例如处理大量临时请求或缓存数据的应用。
- 关注内存效率:希望降低垃圾收集器内存开销和CPU使用率的应用。
::: info
- Shenandoah GC最初在JDK 12中作为实验性功能引入,其最大特点是通过与应用程序线程并发执行大部分工作来尽可能减少GC暂停时间,且暂停时间与堆大小无关。
- 后在JDK 15中,Shenandoah GC从实验性功能转为正式的生产功能,不再需要额外的解锁实验参数,但其默认的垃圾收集器仍然是G1。
- 分代Shenandoah旨在与G1、ZGC(JEP 439已为ZGC引入分代模式)等现代收集器同步发展,同时保持自身在最小化延迟方面的独特优势。 :::
JEP 450: 紧凑对象头(实验性)
::: info JEP 450: Compact Object Headers (Experimental) Reduce the size of object headers in the HotSpot JVM from between 96 and 128 bits down to 64 bits on 64-bit architectures. This will reduce heap size, improve deployment density, and increase data locality. :::
重构了Java对象的内存布局,将 HotSpot JVM 中的普通对象头大小从96到128位减少到64位,从而提升内存利用率和应用性能。
核心原理
Java 对象在堆中的存储包含对象头和实例数据。对象头又分为:
- 标记字 (Mark Word):存储哈希码、GC 年龄、锁状态、线程持有的锁、偏向线程ID、偏向时间戳等运行时数据。
- 类指针 (Class Pointer):指向对象的类元数据。
- 数组长度:数组对象的头部还会额外包含该字段。
在 64 位 JVM 中,普通对象头通常占 12字节(96位) 至 16字节(128位)。对于许多平均大小仅为 32-64 字节的小对象来说,对象头的开销占比非常高,可能达到 20% 到 50%。JEP 450 通过以下方式将对象头压缩至 64 位 (8 字节):
- 压缩类指针:将原本 32 位的压缩类指针进一步优化为 22 位,并将其编码嵌入标记字中。
- 标记字的功能重组与升级:对固定的 64 位标记字空间进行了彻底的重新规划,将其划分为一个精细的功能位域集合,以同时承载原有和新增的信息
- 锁机制革新:传统的偏向锁 和轻量级锁 会覆盖整个标记字(除锁标记位外),与紧凑对象头中必须保留类指针的设计冲突。因此,紧凑对象头不再支持偏向锁和栈锁。它依赖 JDK 22 中引入的对象监视表 来管理重量级锁信息。
新旧对象头布局对比
为了更直观地理解其变化,可以参考下表对传统对象头与紧凑对象头进行的对比:
Java传统对象头
传统对象头大小
| 是否压缩 | 对象类型 | 大小 | 说明 |
|---|---|---|---|
| 压缩 | 普通对象 | 12字节(96位) | 标记字8B(64位)+ 类指针4B(32位) |
| 压缩 | 数组对象 | 16字节(128位) | 标记字8B(64位)+ 类指针4B(32位)+ 数组长度4B(32位) |
| 未压缩 | 普通对象 | 16字节(128位) | 标记字8B(64位)+ 类指针8B(64位) |
| 未压缩 | 数组对象 | 20字节(160位) | 标记字8B(64位)+ 类指针8B(64位)+ 数组长度4B(32位) |
传统对象头标记字(Mark Word)
| 状态 | 锁状态 | 偏向锁 | GC分代 年龄 |
未使用 | 其他 |
|---|---|---|---|---|---|
| 无锁状态 | 01 | 0 | 4位 | 1位 | 哈希码(31位)+ 未使用(25位) |
| 偏向锁状态 | 01 | 1 | 4位 | 1位 | 线程ID(54位)+ epoch(2位) |
| 轻量级锁状态 | 00 | 指向锁记录的指针(62位) | |||
| 重量级锁状态 | 10 | 指向Monitor的指针(62位) | |||
| GC 分代年龄 | 11 | GC所需标记信息 | |||
紧凑对象头
| 标记位 | 自转发标记位 | GC分代年龄 | 预留 | 哈希码 | 压缩类指针 |
|---|---|---|---|---|---|
| 2位 | 1位 | 4位 | 4位 | 31位 | 22位 |
启用方式
Java 24 中,紧凑对象头是实验性功能,需要特定 JVM 参数启用,Java 25 成为正式功能,无需手动启动。
-XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders
适用场景
紧凑对象头尤其适用于以下场景:
- 大量小对象的应用(如微服务、DTO、缓存元素)。
- 内存敏感型工作负载(希望降低内存占用和提高部署密度)。
- 关注缓存效率和高吞吐量的应用。
在决定是否启用时,需考虑:
- 应用程序特性:若应用严重依赖偏向锁,需评估其影响。
- GC 选择:目前该特性主要支持 G1 和 Parallel GC。对于 ZGC 的支持尚未完成。
- 类加载数量:确保应用加载的类数量远低于 400 万的上限。
JEP 472: 准备限制 JNI 的使用
::: info JEP 472: Prepare to Restrict the Use of JNI Issue warnings about uses of the Java Native Interface (JNI) and adjust the Foreign Function & Memory (FFM) API to issue warnings in a consistent manner. All such warnings aim to prepare developers for a future release that ensures integrity by default by uniformly restricting JNI and the FFM API. Application developers can avoid both current warnings and future restrictions by selectively enabling these interfaces where essential. :::
JEP 472(Prepare to Restrict the Use of JNI)是JDK 24中的一个重要提案,旨在增强Java平台的安全性,通过引入对Java本地接口(JNI)使用的限制和警告,为未来版本默认禁止通过JNI或FFM API与本地代码互操作做准备。
核心目标
JEP 472的主要目标包括:
- 保持JNI地位:继续保持JNI作为与本地代码互操作的标准方式的地位。
- 准备生态系统:准备Java生态系统迎接未来的版本,默认不允许通过JNI或FFM API与本地代码互操作。自该版本起,应用程序开发者必须在启动时显式启用JNI和FFM API的使用。
- 统一使用方式:统一JNI和FFM API的使用方式,使库维护者可以在两者之间迁移而无需应用程序开发者更改任何命令行选项。
动机与背景
JNI自JDK 1.1引入以来,一直是Java代码与本地代码(通常用C/C++编写)互操作的主要手段。但它也带来了显著的安全风险:
- 未定义行为与崩溃:调用本地代码可能导致任意的未定义行为,包括JVM崩溃,且Java运行时无法阻止此类问题,也无法抛出可捕获的异常。
- 内存安全风险:本地代码和Java代码经常通过直接字节缓冲区交换数据,这些区域不受JVM垃圾收集器管理。本地代码可能生成由无效内存区域支持的字节缓冲区,在Java代码中使用会引发未定义行为。
- 绕过访问检查:本地代码可以使用JNI访问字段和调用方法,而不经过JVM的任何访问检查,甚至可以改变
final字段的值,从而破坏其他Java代码的一致性。 - 不良GC行为:不正确使用某些JNI函数(如
GetPrimitiveArrayCritical和GetStringCritical)可能导致不良的垃圾回收行为。
JDK 22引入的外部函数与内存(FFM)API作为JNI的现代替代方案,虽然也面临类似风险,但其设计通过“受限方法”和要求开发者显式选择加入来缓解风险。JEP 472旨在使JNI遵循类似的安全范式,这是确保Java平台默认一致性(默认安全)的长期努力的一部分,其他相关举措包括移除sun.misc.Unsafe中的内存访问方法(JEP 471)和限制动态加载代理(JEP 451)。
核心变化
JEP 472的核心变化在于对JNI的“加载和链接本地库”操作施加本地访问限制(Native Access Restrictions),并与FFM API保持一致。
-
受限操作:在JDK 24中,以下操作将默认触发警告(未来版本将抛出异常):
- 调用
System::loadLibrary,System::load,Runtime::loadLibrary或Runtime::load。 - 声明
native方法。
- 调用
-
启用本地访问:应用程序开发者必须显式启用本地访问以避免警告和未来的异常。这可以通过以下方式实现:
- 命令行选项:
# 为类路径上的所有代码启用 java --enable-native-access=ALL-UNNAMED -jar your_app.jar # 为模块路径上的特定模块启用 java --enable-native-access=MODULE1,MODULE2 -jar your_app.jar - 参数文件:在
config-file中写入--enable-native-access=ALL-UNNAMED,然后运行java @config-file -jar myapp.jar - 环境变量传递:
export JDK_JAVA_OPTIONS="--enable-native-access=ALL-UNNAMED",然后运行java -jar myapp.jar - JAR清单属性:在可执行JAR的清单中添加
Enable-Native-Access: ALL-UNNAMED。 - 其他方式:如通过
jlink定制运行时镜像时添加选项,或使用ModuleLayer.Controller::enableNativeAccess方法(其本身是受限方法)。
- 命令行选项:
-
控制限制效果:新的命令行选项
--illegal-native-access用于控制违反限制时的行为:warn(JDK 24默认):允许操作但发出警告(每个模块最多一次)。deny:抛出IllegalCallerException(未来版本的默认行为)。allow:允许操作继续(未来版本会移除)。
未来计划
JEP 472是分阶段实施的长期计划的一部分:
- JDK 24:默认行为是
--illegal-native-access=warn,即发出警告。 - 未来JDK版本:默认行为将变为
--illegal-native-access=deny,即抛出异常,最终实现默认一致性。
重要说明
- 不弃用JNI:JEP 472并非要弃用或移除JNI,也不是要限制本地代码本身的行为。所有本地JNI函数仍然可供本地代码使用。
- 影响范围:此限制主要影响加载本地库和链接native方法的Java代码。仅调用其他模块中声明的
native方法的代码本身不需要启用本地访问。 - FFM API对齐:JNI和FFM API在本地访问限制上保持一致,简化了库的迁移和应用程序的配置。
总结
JEP 472是Java迈向“默认安全” 的重要一步。它通过引入对JNI使用的限制和警告,促使开发者更显式地管理本地代码访问,从而提升应用程序和Java平台整体的安全性和完整性。
虽然这增加了些许配置成本,但为构建更安全可靠的Java生态系统奠定了基础。对于开发者来说,关键是检查现有代码并适时添加--enable-native-access标志。
JEP 475: G1 的 Late Barrier 扩展
::: info JEP 475: Late Barrier Expansion for G1 Simplify the implementation of the G1 garbage collector's barriers, which record information about application memory accesses, by shifting their expansion from early in the C2 JIT's compilation pipeline to later. :::
通过将G1垃圾回收器屏障的生成时机,从C2 JIT编译前期移至后期,简化了其实现。这些屏障的作用是记录有关应用程序内存访问的信息。
JEP 478: 密钥派生函数 API(预览)
::: info JEP 478: Key Derivation Function API (Preview) Introduce an API for Key Derivation Functions (KDFs), which are cryptographic algorithms for deriving additional keys from a secret key and other data. This is a preview API. :::
引入一个用于密钥派生函数的预览版API。密钥派生函数是一种可从密钥及其他数据中推导出更多密钥的密码学算法。
目标:
- 使应用程序能够使用KDF算法,例如基于HMAC的提取-扩展密钥派生函数(HKDF,RFC 5869)和Argon2(RFC 9106)。
- 支持在密钥封装机制(KEM,JEP 452)实现(如ML-KEM)、高层协议(如TLS 1.3中的混合密钥交换)以及密码方案(如混合公钥加密HPKE,RFC 9180)中使用KDF。
- 允许安全提供商使用Java代码或原生代码来实现KDF算法。
- 包含了HKDF的一个实现,并引入了额外的HKDF专用API。
JEP 479: 删除 Windows 32 位 x86 端口
::: info JEP 479: Remove the Windows 32-bit x86 Port Remove the source code and build support for the Windows 32-bit x86 port. This port was deprecated for removal in JDK 21 with the express intent to remove it in a future release. :::
移除针对 Windows 32 位 x86 端口的源代码和构建支持。该端口已在 JDK 21 中被标记为弃用并计划移除,并明确表达了在未来的版本中将其移除的意图。
JEP 483: 提前类加载和链接
::: info JEP 483: Ahead-of-Time Class Loading & Linking Improve startup time by making the classes of an application instantly available, in a loaded and linked state, when the HotSpot Java Virtual Machine starts.Achieve this by monitoring the application during one run and storing the loaded and linked forms of all classes in a cache for use in subsequent runs. Lay a foundation for future improvements to both startup and warmup time. :::
通过让应用程序的类在 HotSpot Java 虚拟机启动时就能立即可用(即已完成加载和链接),来提升启动速度。 其实现方式是:在应用的一次运行期间进行监控,并将所有类的加载和链接形式存储在缓存中以供后续运行使用。 这同时也为未来优化启动与预热时间打下了基础。
JEP 484: 类文件 API
::: info JEP 484: Class-File API Provide a standard API for parsing, generating, and transforming Java class files. :::
提供了一个用于解析、生成和转换 Java 类文件的标准 API,旨在替代第三方库(如 ASM)。
- 解析(Parsing):指的是读取一个已编译的
.class文件,并将其内容(如魔数、版本号、常量池、方法、字段等)分解成程序可以理解和操作的结构化数据模型。 - 生成(Generation):指的是从零开始,通过编程方式动态地创建出一个全新的、符合规范的
.class文件。 - 转换(Transformation):指的是读取一个现有的
.class文件,对其结构进行修改(例如,添加/删除方法、修改字节码指令、植入分析代码等),然后输出修改后的新类文件。 - 标准 API(Standard API):这是最关键的一点。这意味着该API是Java平台本身的一部分(例如在
java.lang.classfile包下),由OpenJDK官方维护和发布。用户无需再引入额外的第三方JAR包。
自第二个预览版以来的更改包括重命名枚举值、删除某些字段、添加方法和方法重载、重命名方法以及删除被认为不必要的接口和方法。
JEP 485: 流收集器
::: info JEP 485: Stream Gatherers Enhance the Stream API to support custom intermediate operations. This will allow stream pipelines to transform data in ways that are not easily achievable with the existing built-in intermediate operations. :::
流收集器(Stream Gatherers)能为Stream API轻松添加自定义的中间操作,实现更复杂的数据转换。
JEP 486: 永久禁用安全管理器
::: info JEP 486: Permanently Disable the Security Manager The Security Manager has not been the primary means of securing client-side Java code for many years, it has rarely been used to secure server-side code, and it is costly to maintain. We therefore deprecated it for removal in Java 17 via JEP 411 (2021). As the next step toward removing the Security Manager, we will revise the Java Platform specification so that developers cannot enable it and other Platform classes do not refer to it. This change will have no impact on the vast majority of applications, libraries, and tools. We will remove the Security Manager API in a future release. :::
安全管理器早已不是保护客户端Java代码的主要手段,在服务端代码中也鲜有应用,且维护成本高昂。因此,该机制已于2021年通过JEP 411在Java 17中被标记为弃用并计划移除。作为移除工作的下一步,Java平台规范将进行修订,使开发者无法启用该功能,并确保其他平台类不再引用它。此项变更对绝大多数应用程序、库和工具不会产生任何影响。Security Manager API将在未来版本中被彻底移除。
JEP 487: 作用域值(第四次预览)
::: info JEP 487: Scoped Values (Fourth Preview) Introduce scoped values, which enable a method to share immutable data both with its callees within a thread, and with child threads. Scoped values are easier to reason about than thread-local variables. They also have lower space and time costs, especially when used together with virtual threads (JEP 444) and structured concurrency (JEP 480). This is a preview API. :::
引入作用域值,使方法能够与线程中的被调用方以及子线程共享不可变数据。作用域值比线程局部变量更容易推理。它们还具有较低的空间和时间成本,特别是当与虚拟线程(JEP 444)和结构化并发(JEP 505)一起使用时。
有一个变动:移除了 ScopedValue 类中的 callWhere 和 runWhere 方法,使 API 保持完全流畅的链式调用特性。现在使用一个或多个绑定作用域值的唯一方式是通过 ScopedValue.Carrier.call 和 ScopedValue.Carrier.run 方法。
JEP 488: 模式、instanceof 和 switch中的原始类型(第二次预览)
::: info JEP 488: Primitive Types in Patterns, instanceof, and switch (Second Preview) Enhance pattern matching by allowing primitive types in all pattern contexts, and extend instanceof and switch to work with all primitive types. This is a preview language feature. :::
通过允许在所有模式上下文中使用原始类型来增强模式匹配,并扩展 instanceof 和 switch 以使用所有原始类型。这是一个预览语言功能。
在所有模式上下文中允许原始类型模式与对应包装类型之间的宽松转换,并支持对记录组件的类型宽松匹配。核心贡献是:
- 原始类型模式与应包装类型之间的宽松转换
- 增强 instanceof 和 switch 构造以支持原始类型模式作为顶级模式:允许在模式匹配中直接使用原始类型(如
int p)来匹配包装类(如Integer)的对象。 - 增强记录模式以支持类型转换:允许在记录模式中使用原始类型来匹配包装类型的记录组件值,无需严格匹配包装类型。
- 增强 instanceof 和 switch 构造以支持原始类型模式作为顶级模式:允许在模式匹配中直接使用原始类型(如
- 对记录组件的类型宽松匹配:在记录模式中使用原始类型来匹配记录的组件值时,无需严格匹配原始类型。这一机制支持在解构记录时自动完成原始类型的加宽转换和有条件的安全缩窄转换,显著提升了代码的简洁性与灵活性。
- 安全性
- 妥善处理 null 值,原始类型模式不会匹配 null,从而避免了潜在的 NullPointerException。
- 对于记录模式中可能造成信息丢失的缩窄转换(如 double → int),模式匹配会在运行时自动检查值的兼容性,仅在不丢失信息时完成匹配,否则返回 false,保障匹配过程的安全性与可靠性。
- 语法与一致性更新:引入了相应的支配性检查规则,在同一个 switch 块中,原始类型模式(如 int i)和其对应的包装类型模式(如 Integer i)不能同时存在,因为它们会互相导致对方不可到达,无论顺序如何都会编译报错。记录模式也遵循相同的类型转换原则,进一步强化了模式匹配整体的语言一致性和表达力。
::: tip 模式 (Pattern)是一个通用概念,指的是在条件判断中同时进行类型检查和变量绑定的操作。例如:obj instanceof String s 就是一个类型模式,它同时检查 obj 是否是 String 类型,如果是,则将其绑定到变量 s。
instanceof 运算符是应用类型模式的第一个地方。从 Java 16 开始,instanceof 后面可以直接跟一个类型模式和变量名。
switch 表达式/语句是应用多种模式(包括类型模式、常量模式等)的更强大场所。在 Java 17 和 21 中,switch 的能力被大幅增强,case 标签可以支持模式。
所以三者关系是:模式匹配是一个范式;instanceof 和 switch 是应用该范式的语法工具。
因此,对JEP 488最准确的理解是:为模式、instanceof 和 switch 添加对原始类型的支持。 :::
::: tip 自动加宽转换: 使用一个“较宽”的类型模式 (double) 去匹配一个“较窄”的组件类型 (int) 的值。编译器允许这种操作,并自动完成安全的值转换。
有条件的安全缩窄转换: 缩窄转换是一种可能丢失信息的转换(例如,将 double 3.14 转换为 int 3 会丢失小数部分),因此不是无条件进行的。
- JVM 会先检查这个 double 值是否能完全精确地转换为一个 int 值(即没有小数部分,且在 int 的取值范围内)
- 如果检查通过:模式匹配成功,变量被赋值
- 如果检查不通过(值太大或有小数):模式匹配直接返回 false,不会赋值,也不会抛出异常
注意:
- “自动加宽转换”和“有条件的安全缩窄转换”要求初始类型和目标类型都是原始类型。 :::
JEP 489: 向量 API(第九个孵化器)
::: info JEP 489: Vector API (Ninth Incubator) Introduce an API to express vector computations that reliably compile at runtime to optimal vector instructions on supported CPU architectures, thus achieving performance superior to equivalent scalar computations. :::
引入一个 API 来表达矢量计算,这些计算在运行时可靠地编译为受支持的 CPU 上的最佳矢量指令,从而实现优于等效标量计算的性能。
JEP 490: ZGC:删除非分代模式
::: info JEP 490: ZGC: Remove the Non-Generational Mode Remove the non-generational mode of the Z Garbage Collector (ZGC), keeping the generational mode as the default for ZGC. :::
移除Z垃圾回收器(ZGC)的非分代模式,保留分代模式作为ZGC的默认配置。
JEP 491: 无需固定即可同步虚拟线程
::: info JEP 491: Synchronize Virtual Threads without Pinning Improve the scalability of Java code that uses synchronized methods and statements by arranging for virtual threads that block in such constructs to release their underlying platform threads for use by other virtual threads. This will eliminate nearly all cases of virtual threads being pinned to platform threads, which severely restricts the number of virtual threads available to handle an application's workload. :::
本改进旨在提升使用同步方法和语句的Java代码的可扩展性。其机制是:当虚拟线程在此类同步结构中阻塞时,会主动释放其占用的平台线程,以供其他虚拟线程使用。此举将消除虚拟线程被“固定”在平台线程上的绝大多数情况,从而避免其对应用工作负载处理能力的严重限制。
JEP 492: 灵活的构造函数体(第三次预览)
::: info JEP 492: Flexible Constructor Bodies (Third Preview) In constructors in the Java programming language, allow statements to appear before an explicit constructor invocation, i.e., super(..) or this(..). The statements cannot reference the instance under construction, but they can initialize its fields. Initializing fields before invoking another constructor makes a class more reliable when methods are overridden. This is a preview language feature. :::
在 Java 编程语言的构造函数中,允许在显式构造函数调用(即 super(..) 或 this(..))之前出现语句。这些语句不能引用正在构建的实例,但可以初始化其字段。在调用另一个构造函数之前初始化字段,可以在方法被重写时提高类的可靠性。这是一个预览语言特性。
JEP 493: 无需 JMOD 即可链接运行时图像
::: info JEP 493: Linking Run-Time Images without JMODs Reduce the size of the JDK by approximately 25% by enabling the jlink tool to create custom run-time images without using the JDK's JMOD files. This feature must be enabled when the JDK is built; it will not be enabled by default, and some JDK vendors may choose not to enable it. ::: 通过让 jlink 工具能够在不依赖 JDK 的 JMOD 文件的情况下创建自定义运行时镜像,可将 JDK 的体积减小约 25%。此功能需在构建 JDK 时手动启用,它不会默认生效,且部分 JDK 供应商可能会选择不启用它。
JEP 494: 模块导入声明(第二次预览)
::: info JEP 494: Module Import Declarations (Second Preview) Enhance the Java programming language with the ability to succinctly import all of the packages exported by a module. This simplifies the reuse of modular libraries, but does not require the importing code to be in a module itself. This is a preview language feature. :::
增强 Java 编程语言,使其能够简洁地导入某个模块所导出的所有包。这简化了模块化库的重用,且调用方代码自身不必是模块化的。这是一项预览语言特性。
使用新特性导入整个模块 假设有一个名为 com.example.utils 的模块,其 module-info.java 文件导出了了一些包:
// module-info.java
module com.example.utils {
exports com.example.utils.math;
exports com.example.utils.logging;
}
在另一个非模块化的应用程序(即没有 module-info.java)中,现在可以使用一种新的导入语句来一次性导入 com.example.utils 模块导出的所有包。
// 使用 'import module' 关键字一次性导入整个模块的所有导出包
import module com.example.utils.*;
public class MyApp {
public static void main(String[] args) {
// 现在可以直接使用被导入模块中所有导出包下的类,而无需逐个导入
// 来自 com.example.utils.math 包
Calculator calc = new Calculator();
double result = calc.add(5, 3.14);
// 来自 com.example.utils.logging 包
Logger logger = new Logger();
logger.info("Result is: " + result);
}
}
与之前方式的对比
- 方式一(传统非模块化项目): 必须逐个导入所需的每个类或包。
import com.example.utils.math.Calculator; import com.example.utils.logging.Logger; // ... 还需要导入其他要用的类 ... - 方式二(模块化项目): 即使只想用一两个类,也必须在自己的 module-info.java 中声明对整个模块的依赖。
::: code-tabs
@tab module-info.java
@tab MyApp.javamodule my.app { requires com.example.utils; // ... 其他依赖 ... }:::import com.example.utils..math.Calculator; - 使用新特性后的方式(简洁且无需模块化):
- 无需自身的 module-info.java。
- 一行语句 import module com.example.utils.*; 即可获得该模块所有导出包的访问权,无需再写多个 import 语句。
之前在 JDK 23 中预览过,本次改动点:
- 解除任何模块都不能声明对 java.base 模块的传递依赖的限制
- 修改 java.se 模块的声明
- 允许 type-import-on-demand 声明遮蔽模块导入声明
JEP 495: 简单源文件和实例主方法(第四次预览)
::: info JEP 495: Simple Source Files and Instance Main Methods (Fourth Preview) Evolve the Java programming language so that beginners can write their first programs without needing to understand language features designed for large programs. Far from using a separate dialect of the language, beginners can write streamlined declarations for single-class programs and then seamlessly expand their programs to use more advanced features as their skills grow. Experienced developers can likewise enjoy writing small programs succinctly, without the need for constructs intended for programming in the large. This is a preview language feature. :::
扩展 Java 编程语言,使初学者无需了解专为大型程序设计的语言功能,即可编写自己的第一个程序。初学者无需使用某种独立的语言变体,即可为单类程序编写简化的声明,然后随着技能的增长无缝扩展他们的程序以使用更高级的功能。经验丰富的开发者同样可以简洁地编写小型程序,而不必使用那些为大规模编程设计的结构。
简单说就是省略显式类声明和 public static 修饰符,简化输出语句,来简化入门代码和脚本开发。
void main() {
println("Hello Java 23!"); // 隐式调用 System.out.println
}
改动点:将隐式声明的类和实例主方法重命名为简单源文件和实例主要方法
JEP 496: 基于抗量子模块格的密钥封装机制
::: info JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism Enhance the security of Java applications by providing an implementation of the quantum-resistant Module-Lattice-Based Key-Encapsulation Mechanism (ML-KEM). Key encapsulation mechanisms (KEMs) are used to secure symmetric keys over insecure communication channels using public key cryptography. ML-KEM is designed to be secure against future quantum computing attacks. It has been standardized by the United States National Institute of Standards and Technology (NIST) in FIPS 203. :::
通过提供抗量子的基于模块格的密钥封装机制(ML-KEM)实现,增强Java应用程序的安全性。密钥封装机制(KEM)利用公钥密码学,在不安全通信信道中保护对称密钥的安全传输。ML-KEM的设计旨在抵御未来量子计算攻击,并已由美国国家标准与技术研究院(NIST)在FIPS 203中完成标准化。
JEP 497: 基于模块格的抗量子数字签名算法
::: info JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm Enhance the security of Java applications by providing an implementation of the quantum-resistant Module-Lattice-Based Digital Signature Algorithm (ML-DSA). Digital signatures are used to detect unauthorized modifications to data and to authenticate the identity of signatories. ML-DSA is designed to be secure against future quantum computing attacks. It has been standardized by the United States National Institute of Standards and Technology (NIST) in FIPS 204. :::
通过提供抗量子计算的基于模块格的数字签名算法(ML-DSA)实现,增强Java应用程序的安全性。数字签名技术用于检测数据的非法篡改,并对签名者身份进行认证。ML-DSA的设计旨在抵御未来量子计算攻击,并已由美国国家标准与技术研究院(NIST)在FIPS 204中完成标准化。
JEP 498: 在 sun.misc.Unsafe 中使用内存访问方法时发出警告
::: info JEP 498: Warn upon Use of Memory-Access Methods in sun.misc.Unsafe Issue a warning at run time on the first occasion that any memory-access method in sun.misc.Unsafe is invoked. All of these unsupported methods were terminally deprecated in JDK 23. They have been superseded by standard APIs, namely the VarHandle API (JEP 193, JDK 9) and the Foreign Function & Memory API (JEP 454, JDK 22). We strongly encourage library developers to migrate from sun.misc.Unsafe to supported replacements, so that applications can migrate smoothly to modern JDK releases. :::
在运行时首次调用 sun.misc.Unsafe 中的任何内存访问方法时发出警告。 所有这些不受支持的方法已在 JDK 23 中被最终标记为弃用。它们已被标准 API 所取代,即 VarHandle API(JEP 193,JDK 9)和外部函数与内存 API(JEP 454,JDK 22)。强烈建议库开发者从 sun.misc.Unsafe 迁移至受支持的替代方案,以确保应用能够顺利过渡到现代 JDK 版本。
创建 sun.misc.Unsafe 类是为了为 Java 类提供一种执行低级操作的机制。它的大多数方法用于访问内存,无论是在 JVM 的垃圾收集堆中还是在堆外内存中,这些内存不受 JVM 控制。正如类名所示,这些内存访问方法是不安全的。
JEP 499: 结构化并发(第四次预览)
::: info JEP 499: Structured Concurrency (Fourth Preview) Simplify concurrent programming by introducing an API for structured concurrency. Structured concurrency treats groups of related tasks running in different threads as a single unit of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability. This is a preview API. :::
通过引入结构化并发 API 来简化并发编程。结构化并发将不同线程中运行的相关任务组视为单个工作单元,从而简化错误处理和取消,提高可靠性并增强可观测性。这是一个预览 API。
JEP 501: 弃用 32 位 x86 端口并将其删除
::: info JEP 501: Deprecate the 32-bit x86 Port for Removal Deprecate the 32-bit x86 port, with the intent to remove it in a future release. This will thereby deprecate the Linux 32-bit x86 port, which is the only 32-bit x86 port remaining in the JDK. It will also, effectively, deprecate any remaining downstream 32-bit x86 ports. After the 32-bit x86 port is removed, the architecture-agnostic Zero port will be the only way to run Java programs on 32-bit x86 processors. :::
弃用 32 位 x86 端口,并计划在未来版本中将其移除。此举将导致目前 JDK 中唯一剩余的 32 位 x86 端口——Linux 32 位 x86 端口被弃用,同时也将实质上弃用所有下游衍生的 32 位 x86 移植版本。在该端口被移除后,与架构无关的 Zero 移植版本将成为在 32 位 x86 处理器上运行 Java 程序的唯一方式。