Java 25 发布,性能提升与新特性全解析
前言
Java 25 于 2025 年 9 月 16 日正式发布,标志着多项关键语言、虚拟机与安全特性的成熟落地。本文依据官方 JEP 文档,对 Java 25 中已最终确定(Finalized) 的核心特性进行逐项深度解析,涵盖语义细节、使用约束、典型场景与最佳实践,并对预览/实验性特性予以准确标注。
文章目录
- 前言
1. JEP 511:模块导入声明(Module Import Declarations)
1.1 功能概述
模块导入声明(import module M;)允许开发者通过单一语句导入一个模块所导出的所有公共顶级类型(类与接口),并自动包含该模块通过 requires transitive 依赖的其他模块所导出的包。
1.2 语义规则
- 作用范围:适用于任意源文件,无论是否属于显式模块。
- 导入内容:
- 模块
M向当前模块(或 unnamed module)导出(exported) 的所有包中的public顶级类型; - 所有因
M声明了requires transitive N而被当前模块可读(readable) 的模块N所导出的包中的public顶级类型。
- 模块
- 不导入内容:
- 限定导出(qualified exports)给其他模块的包(除非当前模块是目标模块);
- 未导出的包;
- unnamed module(即 classpath 上的代码)。
1.3 名称消歧机制
模块导入可能引入同名类型冲突。Java 编译器遵循以下阴影规则(shadowing) 解析名称:
- 单类型导入(Single-type import):如
import java.sql.Date;—— 优先级最高; - 按需包导入(Type-import-on-demand):如
import java.util.*;; - 模块导入(Module import):如
import module java.base;—— 优先级最低。
示例:
import module java.base; // 导入 java.util.Date
import module java.sql; // 导入 java.sql.Date
import java.sql.Date; // 消歧:Date 指向 java.sql.Date
public class Example {
Date d; // OK: java.sql.Date
}
1.4 典型应用场景
- 简化标准库使用:
import module java.base; // 等效于 54 个 import pkg.*; List<String> list = List.of("a", "b"); Path p = Path.of("/tmp"); - 聚合模块导入:
// java.se 是聚合模块,transitively requires java.base 等 import module java.se; // 导入整个 Java SE API(123 个包)
1.5 与紧凑源文件的集成
在紧凑源文件中,import module java.base; 自动生效,无需显式声明。
1.6 与 Java 24 的差异
- 从 Second Preview(JEP 494) 转为 Final;
java.se模块现已声明requires transitive java.base,使import module java.se能完整覆盖标准 API。
2. JEP 512:紧凑源文件与实例主方法(Compact Source Files and Instance Main Methods)
2.1 功能组成
该特性包含两个正交但互补的改进:
- 紧凑源文件(Compact Source File):允许省略顶层类声明;
- 实例主方法(Instance Main Method):允许
main方法为非static。
二者共同降低初学者与脚本编写者的认知负担。
2.2 紧凑源文件语义
- 编译器隐式生成一个
final顶层类(位于 unnamed package),其成员即为源文件中的字段与方法; - 该类无显式名称,不可通过
new实例化; - 自动导入
java.base模块所有导出类型(等效于import module java.base;); - 必须包含一个可启动的
main方法(见 2.3)。
示例:
// Greet.java
String greeting = "Hello";
String buildMessage(String name) {
return greeting + ", " + name + "!";
}
void main() {
IO.println(buildMessage("Java 25"));
}
2.3 实例主方法协议
JVM 启动时按以下顺序选择 main 方法:
- 若存在
public static void main(String[]),则调用之; - 否则,若存在无参
main()方法(任意访问修饰符、任意返回类型,但通常为void),则:- 若为
static,直接调用; - 若为实例方法,则:
- 要求类存在非私有无参构造器;
- 实例化对象后调用其
main()方法。
- 若为
注意:实例 main 方法不能声明参数。
2.4 java.lang.IO 类
- 位于
java.lang,自动可用; - 提供基础控制台 I/O:
public static void print(Object obj); public static void println(Object obj); public static void println(); public static String readln(String prompt); public static String readln(); - 不再自动静态导入:必须写
IO.println(...),避免魔法行为,便于平滑迁移到普通类。
2.5 程序演进路径
紧凑源文件可无缝演进为普通类:
// 紧凑版
void main() {
var list = List.of("a", "b");
IO.println(list);
}
// 演进为普通类
import module java.base;
class MyApp {
void main() {
var list = List.of("a", "b");
IO.println(list);
}
}
2.6 与 Java 24 的差异
- 名称由 “Simple Source Files” 改为 “Compact Source Files”;
IO类移至java.lang;- 移除
IO静态方法的自动导入; - 实现基于
System.in/out,而非Console。
3. JEP 513:灵活的构造函数体(Flexible Constructor Bodies)
3.1 核心变更
允许在显式构造器调用(super(...) 或 this(...))之前编写语句(称为 prologue),但受限于 early construction context 规则。
3.2 执行模型
构造过程分为两个阶段:
- Prologue(自底向上执行):子类 → 父类;
- Epilogue(自顶向下执行):
Object→ 子类。
此模型确保子类字段可在父类构造器执行前初始化,避免因父类调用被覆写方法而访问未初始化字段。
3.3 Early Construction Context 约束
在 prologue 中(含 super(...) 参数列表):
- 禁止使用
this(显式或隐式)访问实例字段或方法; - 禁止使用
super访问父类成员; - 允许对无初始值器(no initializer) 的本类字段进行赋值;
- 允许访问外围类(enclosing class) 的实例(针对内部类)。
合法示例:
class Employee extends Person {
String officeID; // 无初始值器
Employee(int age, String officeID) {
if (age < 18 || age > 67)
throw new IllegalArgumentException("Invalid age");
this.officeID = officeID; // OK: 初始化本类字段
super(age); // 调用父类构造器
}
}
非法示例:
class X {
int i;
String s = "hello";
X() {
var x = i; // Error: 隐式 this.i
s = "goodbye"; // Error: s 已有初始值器
super();
}
}
3.4 安全性提升
解决经典问题:父类构造器调用被覆写方法时,子类字段尚未初始化。
修复前:
class Person {
Person(int age) {
this.age = age;
show(); // 调用 Employee.show(),但 officeID 为 null
}
}
class Employee extends Person {
String officeID;
Employee(int age, String officeID) {
super(age);
this.officeID = officeID;
}
void show() { IO.println("Office: " + officeID); } // prints null
}
修复后:
class Employee extends Person {
String officeID;
Employee(int age, String officeID) {
this.officeID = officeID; // 先初始化
super(age); // 再调用父类
}
}
// now prints "Office: CAM-FORA"
3.5 与 Java 24 的差异
- 从 Third Preview(JEP 492) 转为 Final,无变更。
4. JEP 519:紧凑对象头(Compact Object Headers)
4.1 技术背景
HotSpot 中每个 Java 对象包含一个对象头。传统布局在 64 位 JVM 上占用 12 字节(8 字节 Mark Word + 4 字节 Klass Word,对齐至 16 字节)。
紧凑对象头通过压缩 Klass 指针与 Identity Hash Code,将头大小缩减至 8 字节。
4.2 性能收益(来自 JEP 519)
- SPECjbb2015:
- 堆内存减少 22%;
- CPU 时间减少 8%;
- GC 次数减少 15%(G1 与 Parallel GC);
- 高并行 JSON 解析:运行时间减少 10%。
4.3 启用方式
Java 25 起,启用方式简化为:
$ java -XX:+UseCompactObjectHeaders MyApp
不再需要 -XX:+UnlockExperimentalVMOptions。
4.4 非目标
- 不设为默认:未来版本可能默认启用,但 Java 25 中仍需显式开启;
- 保留扩展性:已为 Project Valhalla 预留 4 位,必要时可进一步压缩。
5. JEP 521:分代 Shenandoah(Generational Shenandoah)
5.1 功能定位
Shenandoah GC 原为不分代设计。JEP 404(JDK 24)引入实验性分代模式,将堆划分为 Young 与 Old 区域,优化短生命周期对象回收。
Java 25 将其转为 Product Feature。
5.2 启用方式
$ java -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational MyApp
不再需要 -XX:+UnlockExperimentalVMOptions。
5.3 适用场景
- 应用具有明显对象生命周期分化(大量短命对象);
- 需要 Shenandoah 的低暂停特性 + 分代回收的吞吐优势。
5.4 非目标
- 不改变默认模式:Shenandoah 仍默认使用不分代模式。
6. JEP 503:移除 32 位 x86 端口
6.1 变更内容
正式移除对 Linux 32 位 x86 平台的支持。
6.2 原因
- 社区使用率极低;
- 维护成本高,阻碍新特性(Loom、FFM、向量 API)在该端口的实现;
- 主流硬件已全面转向 64 位。
6.3 影响
受影响用户应迁移至 64 位 JVM(x64 或 AArch64)。
7. 预览与实验性特性概览
以下特性在 Java 25 中仍处于预览或实验阶段,需显式启用:
| JEP | 特性 | 状态 | 启用方式 |
|---|---|---|---|
| 470 | PEM 编码的密码学对象 | 预览 | --enable-preview |
| 502 | 稳定值(Stable Values) | 预览 | --enable-preview |
| 505 | 结构化并发 | 第五次预览 | --enable-preview |
| 507 | 原始类型在模式匹配、instanceof 和 switch 中的使用 | 第三次预览 | --enable-preview |
| 508 | 向量 API | 第十次孵化 | 默认启用(孵化特性) |
| 509 | JFR CPU 时间剖析 | 实验性 | -XX:+UnlockExperimentalVMOptions(仅 Linux) |
| 514 | 提前编译命令行优化 | Leyden 实验 | -XX:AOTCacheOutput=... |
| 515 | 提前编译方法剖析 | Leyden 实验 | 同上 |
| 518 | JFR 协作采样 | 实验性 | 默认启用(HotSpot/JFR) |
| 520 | JFR 方法计时与追踪 | 实验性 | 默认启用(HotSpot/JFR) |
注意:预览特性(Preview)需
--enable-preview;实验性特性(Experimental)通常需-XX:+UnlockExperimentalVMOptions,但部分 JFR 特性已默认可用。
总结
Java 25 在语言表达力、内存效率与 GC 能力上取得显著进展:
- 语言层面:通过模块导入、紧凑源文件、灵活构造器,大幅降低入门门槛与样板代码;
- 虚拟机层面:紧凑对象头与分代 Shenandoah 为内存敏感与低延迟应用提供更强支撑;
- 工程演进:移除过时端口,聚焦资源于现代架构。
这些特性共同体现了 Java “渐进式现代化” 的核心哲学——在保持向后兼容的前提下,持续提升开发者体验与运行时性能。
更多推荐



所有评论(0)