JDK25预计2025-09-16发布,是最新的长期支持版本(LTS),上一个LTS版本是JDK21。
本次JDK 25共带来18个JEP,信息量很大。
一. JEP 470: 隐私增强邮件(PEM)提供支持(预览)
引入一个 API,用于将表示加密密钥、证书和证书吊销列表的对象编码为广泛使用的隐私增强邮件 (PEM) 传输格式,并将该格式解码回对象。这是一个预览版 API。
将会在java.security包中引入三个类:
1. DEREncodable 接口由 Java 平台 API 类实现,这些类表示具有二进制编码密钥或证书材料的加密对象。
2. PEMEncoder 和 PEMDecoder 类用于对 PEM 格式进行编码和解码。这些类的实例是不可变且可重用的,即它们不保留来自先前编码或解码的加密对象的信息。
3. PEMRecord 类(实现 DEREncodable 接口)用于对表示加密对象的 PEM 文本进行编码和解码,这些加密对象在 Java 平台 API 中尚无对应支持。
预览API需要启用预览功能才能使用:
编译程序时增加参数:
--enable-preview
二. JEP 502: Stable Values(预览)
翻译成稳定值有点奇怪,还是叫Stable Values顺口一点。
Stable Values 是 Java 平台新引入的一种 API,它可以帮助开发人员更好地管理和控制对象的状态和生命周期。相比于传统的final修饰字段,Stable Values 提供了更加灵活的初始化时机,同时也保证了对象状态的不可变性,从而允许更有效的性能优化和避免多线程环境中的数据竞争问题。
与final相比,Stable Values 支持在构造函数或类初始化之外的时间点进行初始化,这一点显得其更加灵活。
预览API需要启用预览功能才能使用:
编译程序时增加参数: --enable-preview
来个🌰:
以前定义不可变的变量:
class ProductController {
private final Logger logger = Logger.create(ProductController.class);
void submitOrder(User user, List<Product> products) {
logger.info("started");
...
logger.info("submitted");
}
}
logger属于类属性,每次创建都必须预先初始化此属性,导致启动过程缓慢。
新方式:
class ProductController {
// OLD:
// private Logger logger = null;
// NEW:
private final StableValue<Logger> logger = StableValue.of();
Logger getLogger() {
return logger.orElseSet(() -> Logger.create(ProductController.class));
}
void submitOrder(User user, List<Product> products) {
getLogger().info("started");
...
getLogger().info("submitted");
}
}
类初始化时logger不包含任何内容,如果已设置值就不会再次设置,值仅会被设置一次,且设置后值不可变。
初始化时机很灵活,你可以在想用的时候在进行初始化。
也可以像下面这样写,定义时并不会初始化(只有在实际调用时才会触发初始化):
private final Supplier<Logger> logger = StableValue.supplier(() -> Logger.create(OrderController.class));
调用方式需要改为:
logger.get().info("started");
提升点:1. JVM可进行常量折叠优化;2. 初始化时机灵活,加快类的初始化。
三. JEP 503: 删除32位x86端口
没啥说的,删除就删除吧。
四. JEP 505: 结构化并发(第五次预览)
不知道多久会正式可用,期待值拉满了。
从JDK 19开始孵化,到JDK 25还在预览。
JDK 25进行了一些API变更,StructuredTaskScope 现在通过静态工厂方法 而非公共构造函数进行初始化。零参数的 open 工厂方法覆盖了常见场景,即创建一个 StructuredTaskScope 实例,用于等待所有子任务成功或任意子任务失败。若需实现其他策略和结果,可通过向更复杂的 open 工厂方法提供合适的 Joiner 来实现 。
新的写法如下:
Response handle() throws InterruptedException {
try (var scope = StructuredTaskScope.open()) {
Subtask<String> user = scope.fork(() -> findUser());
Subtask<Integer> order = scope.fork(() -> fetchOrder());
scope.join(); // Join subtasks, propagating exceptions
// Both subtasks have succeeded, so compose their results
return new Response(user.get(), order.get());
}
}
结构化并发 API 的核心类是 StructuredTaskScope,位于 java.util.concurrent 包中。此类允许我们将一个任务组织为一组并发子任务,并作为一个整体进行协调。子任务通过单独 fork 在各自的线程中执行,随后作为一个整体进行 join。StructuredTaskScope 将子任务的生命周期限制在一个清晰的作用域内,所有任务与子任务的交互(包括 fork、join、错误处理及结果组合)均在此作用域内完成 。
五. JEP 506: Scoped Values
经历5个版本,终于正式可用。
用来在线程间共享变量,也可以说是用来替换臭名昭著的ThreadLocal。
来个🌰:
private static final ScopedValue<FrameworkContext> CONTEXT
= ScopedValue.newInstance(); // (1)
void serve(Request request, Response response) {
var context = createContext(request);
where(CONTEXT, context) // (2)
.run(() -> Application.handle(request, response));
}
public PersistedObject readKey(String key) {
var context = CONTEXT.get(); // (3)
var db = getDBConnection(context);
db.readKey(key);
}
相比ThreadLocal,ScopedValue的优势在于:
1. 作用域绑定与自动失效
ScopedValue 的值与其声明的作用域紧密绑定,作用域结束后值会自动失效,无需手动清理资源。这避免了 ThreadLocal 可能因线程复用导致的内存泄漏问题。例如,在结构化并发中,ScopedValue 的生命周期与任务作用域对齐,确保子任务结束时自动释放资源。
2. 不可变性设计
ScopedValue 是不可变的(Immutable),一旦绑定值后无法修改,这消除了多线程环境下因共享可变状态引发的线程安全问题。而 ThreadLocal 允许线程内修改变量副本,可能带来数据不一致风险。
3. 内存效率与性能优化
根据 JDK 官方测试数据,ScopedValue 在相同并发规模下相比 ThreadLocal 可节省高达 40% 的内存资源。这一优势使其更适合高并发场景(如 Web 开发、微服务架构)。
4. 专为虚拟线程优化
ScopedValue 针对 Java 虚拟线程(Virtual Thread)设计,支持高效的线程本地数据管理。相比之下,ThreadLocal 在虚拟线程大规模使用时可能因线程数量激增导致内存压力。
5. 权限控制与封装性
即使在同一个线程中,ScopedValue 的值也不能被随意修改。修改操作仅在声明的作用域内生效,超出作用域后修改无效,这增强了数据访问的安全性。
六. JEP 507: switch,instanceof,模式匹配中的基础类型(第三次预览)
主要包含:
1. 允许在switch语句中使用原始类型模式,从而改进代码的可读性和减少冗余;
2. 解除对记录模式中原始类型使用的限制,使得开发人员能够更方便地处理包含原始类型的数据;
3. 放宽instanceof操作符的使用规则,使其不仅限于引用类型,还可以用于检测原始类型之间的安全转换;
4. 引入常量模式的支持,这将使switch语句更加灵活并提高代码的可读性。
来个例子:
byte b = 42;
b instanceof int; // true(无条件精确转换)
int i = 42;
i instanceof byte; // true(精确转换)
int i = 1000;
i instanceof byte; // false(非精确转换)
int i = 16_777_217; // 2^24 + 1
i instanceof float; // false(非精确转换)
i instanceof double; // true(无条件精确转换)
i instanceof Integer; // true(无条件精确转换)
i instanceof Number; // true(无条件精确转换)
float f = 1000.0f;
f instanceof byte; // false
f instanceof int; // true(精确转换)
f instanceof double; // true(无条件精确转换)
double d = 1000.0d;
d instanceof byte; // false
d instanceof int; // true(精确转换)
d instanceof float; // true(精确转换)
Integer ii = 1000;
ii instanceof int; // true(精确转换)
ii instanceof float; // true(精确转换)
ii instanceof double; // true(精确转换)
Integer ii = 16_777_217;
ii instanceof float; // false(非精确转换)
ii instanceof double; // true(精确转换)
对于引用类型,若漏掉 instanceof 检查,不安全的强制转换会抛出 ClassCastException,从而阻止错误值的传播;但原始类型的不安全转换(如 int 到 byte)可能因精度丢失、符号丢失等问题导致静默错误,使错误值流入程序后续逻辑,引发潜在缺陷。
如果左侧值可通过精确转换转为右侧类型,则 instanceof 返回 true,表明强制转换是安全的。
七. JEP 508: Vector API(第十次孵化)
还早,这个JEP需要等Project Valhalla的必要功能作为预览功能提供,适配Project Valhalla之后才能进入下一步。
这个JEP用于向量计算,这些计算在运行时可被可靠地编译为受支持 CPU 上的最优向量指令,从而实现优于等效标量计算的性能。
八. JEP 509: JFR CPU时间分析(实验)
增强 JDK Flight Recorder (JFR) 以在 Linux 上捕获 CPU 时间分析信息。这是一项实验性功能。
九. JEP 510: 密钥派生函数
引入一个用于密钥派生函数(KDFs)的 API,该函数是一种加密算法,可根据秘密密钥和其他数据派生出额外的密钥。
十. JEP 511: 模块导入声明
增强 Java 编程语言,允许简洁地导入模块导出的所有包 ,简化模块化库的复用,且不要求导入代码本身必须是模块 。
CRUD用的比较少。
语法:
import module ModuleName;
示例:
import module java.base; // 导入 java.base 导出的所有包(如 java.util.*)
import module java.sql; // 导入 java.sql 及其传递依赖(如 java.xml)的导出包。
慎用,感觉性能堪忧。可能会被人打残。
十一. JEP 512: 压缩源文件和main方法
一言以蔽之,简化初学者学习Java的门槛。
最开始的Hello World:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
后面的:
class HelloWorld {
void main() {
System.out.println("Hello, World!");
}
}
继续:
void main() {
System.out.println("Hello, World!");
}
现在:
void main() {
IO.println("Hello, World!");
}
我们当初学的最复杂的算什么?!!!!(算倒霉)
还有更甚之,有人还记得Scanner吗?就是从控制台读取用户输入。
现在变成这样了:
void main() {
String name = IO.readln("Please enter your name: ");
IO.print("Pleased to meet you, ");
IO.println(name);
}
无言以对,当初吃的是什么糟糠!
自动导入java.base模块的所有导出包(比如: java.util,java.io等)
void main() {
var list = List.of(1, 2, 3); // List 直接可用
IO.println(list);
}
十二. JEP 513: 灵活构造函数
允许在 Java 构造函数中编写更灵活的代码,包括在调用 super(...) 之前执行任意代码(如参数校验、共享初始化逻辑),从而提升代码可读性和对象完整性,同时不违反 Java 的安全性约束 。
示例:
class Person {
Person(String name) {
if (name == null) throw new IllegalArgumentException(); // 参数校验
super(); // 允许在此之后调用
this.name = name;
}
}
十三. JEP 514: AOT编译命令行易用性改进
通过简化常见用例所需的命令,使创建提前编译缓存 (AOT Cache)的过程更便捷。提前编译缓存可加速 Java 应用程序的启动,而新特性通过单步操作替代传统的两步流程(记录配置 → 生成缓存),减少用户操作复杂度 。
十四. JEP 515: AOT方法性能分析
JEP 515 通过将方法执行分析数据提前收集并存储到 AOT 缓存中,显著缩短了 Java 应用程序的预热时间。这一改进对需要快速达到性能峰值的场景(如云服务自动扩展、短生命周期任务)尤为重要 。
十五. JEP 518: JFR协同采样
改进 JDK Flight Recorder (JFR) 的线程堆栈异步采样机制,通过将采样操作与应用程序定义的安全点对齐,提升其稳定性和性能。
十六. JEP 519: 紧凑对象标头
压缩对象标头,减少空间占用,提升CPU利用率,减少垃圾回收次数。
十七. JEP 520: JFR方法时序和跟踪
扩展 JDK Flight Recorder (JFR),使其具有通过字节码插桩进行方法计时和跟踪的功能。
十八. JEP 521: Shenandoah分代模式
自 JDK 25 起,Shenandoah 支持分代回收(年轻代 + 老年代),将对象按生命周期分代处理,减少全堆扫描频率。这一模式在 DaCapo 和 SPECjbb2015 测试中,停顿时间减少 20%-30%,尤其适合大堆内存(如 1TB)场景 。