Java 25 新特性及示例
Java 25 的改进使学习与专业发展更轻松高效。紧凑型程序助力新手快速入门,并发性、性能及安全性的增强则为资深开发者带来更稳健、可扩展的应用程序。
Java 25 新特性及示例

Java 25 于 2025年9月16日 正式发布。作为长期支持(LTS)版本,它涵盖了核心 Java 库、语言规范、安全性和性能等多方面的重大增强。Oracle 计划为 Java 25 提供至少八年的支持,使组织能够按自身节奏迁移,同时受益于最新特性,包括增强的人工智能能力与开发者生产力提升。
作为最新的长期支持版本,Java 25在语言语法、API、安全性、性能及监控方面均实现重大升级,使Java对所有用户更易用且更强大。所有新特性均通过JDK增强提案(JEP)引入,因此各章节将列出对应JEP、概述升级内容并提供实用代码示例或应用场景。
目录
- JEP 507:模式匹配、instanceof 和 switch 语句中的基本类型(第三版预览)
- JEP 512:紧凑源文件与实例主方法
- JEP 513:灵活构造函数主体
- JEP 511:模块导入声明
- JEP 505:结构化并发(第五版预览)
- JEP 506:作用域值
- JEP 502:稳定值(预览版)
- JEP 510:密钥派生函数 API
- JEP 470:密码对象的PEM编码(预览)
- JEP 508:向量 API(第十孵化器)
- JEP 519:紧凑对象头
- JEP 521:代际 Shenandoah
- JEP 514:提前编译命令行工具的易用性
- JEP 515:预编译方法性能分析
- JEP 503:移除 32 位 x86 端口
- JEP 509:JFR CPU 时间分析
- JEP 518:JFR协作采样
- JEP 520:JFR方法计时与追踪
- Java 25新特性完整JEP列表及示例
- 结论
JEP 507:模式匹配、instanceof 和 switch 语句中的基本类型(第三版预览)
该功能旨在通过允许所有类型(无论是基本类型还是引用类型)使用类型模式,实现统一的数据探索。此功能最初由JEP 455提出(参见JDK 23),后经JEP 488重新预览 (JDK 24) 重新预览,内容未作修改。在 JDK 25 中,该提案第三次作为预览功能提交,内容保持不变。
Java模式匹配现已支持基本类型,可简化代码并减少错误。该特性支持直接、类型安全的模式匹配与基本类型解构,无需冗余装箱或冗长代码。基本类型的模式匹配案例简化了switch和instanceof语法,使基本类型的模式匹配更具表达力:
示例#1:
Object obj = 42;
switch (obj) {
case int i -> System.out.println("Primitive int: " + i);
case double d -> System.out.println("Primitive double: " + d);
default -> System.out.println("Something else");
}
示例#2:
Integer code=-1;
switch (code) {
case int n when n > 0 -> System.out.println("Positive int: " + n);
case int n when n < 0 -> System.out.println("Negative int: " + n);
default -> System.out.println("Zero");
}
这避免了不必要的强制转换、装箱/拆箱操作,使代码更加简洁。
示例#3:
Object obj = 10;
if (obj instanceof int val) {
System.out.println("Primitive int value: " + val);
} else if (obj instanceof double val) {
System.out.println("Primitive double value: " + val);
}
在此,基本类型模式匹配使 instanceof 不仅适用于引用类型,还适用于 int、double 等基本类型。它消除了手动拆箱和类型转换的冗余代码。在旧版Java中,开发者需显式编写转换逻辑。若obj兼容(例如int对应包装的Integer,double对应Double),匹配成功即可直接使用原始变量。这种方式在处理泛型类型或包装值时,显著提升了类型安全性和代码可读性。
JEP 512:紧凑源文件与实例主方法
该功能最初在Java SE 21中作为JEP 445(无名类与实例主方法预览版)发布,后于Java SE 22、23、24版本持续预览,本次正式版以修订标题“紧凑源文件与实例主方法”永久纳入。
本次更新内容如下:
- 关键变更涉及基础控制台 I/O 类 IO 的包位置,现移入 java.lang 包。此调整意味着该类对所有 Java 源文件隐式可见。
- 对于紧凑源文件,IO类的静态方法不再被隐式导入。除非使用特定的静态导入语句,否则方法调用必须添加类名前缀,例如IO.println(“Hello, world!”)。
- IO类的实现已重构;它现在作为System.out和System.in的封装器运行,取代了其对java.io.Console类的先前依赖。
您可查看该功能在 Java 24 版本中的状态(JEP-495)。
JEP 513:灵活构造函数主体
该特性最初在 Java SE 22 中作为 JEP 447:super(…) 之前的语句(预览版)进行预览,随后在 Java SE 23 和 Java SE 24 中再次预览。本次发布中该特性已永久保留,未作重大改动。
该特性允许在显式构造函数调用(super(…)或this(…))之前,于前置代码段执行语句。您现在可在调用父类构造函数前进行输入验证、执行计算或调用辅助方法。但在此上下文中仍无法引用正在构造的对象(不可使用this,不可访问未初始化的字段)。
核心新特性:
- 超类构造前的输入验证
- 计算或准备传递给超类的参数
- 更简洁安全的对象构造,在高成本分配前快速失败
限制条件
- 在构造器链式调用前,不可读取
this字段或调用实例方法 - 字段可以初始化,但不得泄露对部分构造对象的引用。
- 在此父类构造前区域,允许使用大多数静态方法和局部辅助函数。
示例#1:防御性编程(参数验证):
public class PositiveBigInteger extends BigInteger {
public PositiveBigInteger(long value) {
if (value <= 0) throw new IllegalArgumentException("Value must be positive");
super(Long.toString(value));
}
}
此处通过验证机制防止向父类传递无效值。
**示例#2:条件调用父类构造函数:
**
public class CustomLogger extends Logger {
public CustomLogger(String config) {
String level = "INFO";
if ("debug".equals(config)) {
level = "DEBUG";
}
super(level); // can compute before super()
}
}
参数计算在父类分配之前完成。
示例#3:辅助方法调用:
public class Metric extends DataPoint {
public Metric(String key) {
String normalizedKey = normalizeKey(key);
super(normalizedKey);
}
private static String normalizeKey(String key) {
return key.trim().toLowerCase();
}
}
辅助方法可在超类构造器之前执行。
示例#4:记录构造器与JEP 513:
public record ValidatedPoint(int x, int y) {
public ValidatedPoint(int x, int y) {
checkNonNegative(x, y); // now allowed before this()
this(x, y);
}
private static void checkNonNegative(int x, int y) {
if (x < 0 || y < 0) throw new IllegalArgumentException();
}
}
非规范记录构造器可受益于此灵活性。
示例#5:枚举构造器:
public enum Status {
ACTIVE("A"), INACTIVE("I");
private final String code;
Status(String code) {
if (!code.matches("[AI]")) throw new IllegalArgumentException();
this.code = code;
}
}
字段初始化前可进行验证。
JEP 511:模块导入声明
该特性首次在Java SE 23预览,并在Java SE 24再次预览。现提议在本版本最终确定,无重大变更。
该特性为Java语言引入模块导入声明,允许开发者通过单条语句导入模块中所有导出包的公共类型:
import module <ModuleName>;
使用import module语句,一步导入模块内所有导出类。模块导入声明的引入旨在通过以下关键方式简化软件开发:
**1) 简化库使用:**通过单一声明即可导入模块中的所有类型,简化模块化库的使用流程。
**2) 减少导入冗余:**用单个简洁的模块导入声明替代多个通配符包导入,有效减少代码冗余。
3) 降低学习门槛: 新手无需事先了解具体包位置,即可轻松使用核心Java类和第三方库。
4) 兼容性保障: 确保新型模块导入声明与传统包导入语句无冲突共存。
5) 支持渐进式采用: 即使开发者自有代码库尚未完全模块化,仍可受益于模块导入功能。
该功能的示例与详细说明已在Java 24的模块导入声明(JEP-494, 第二版预览)中详述。
模块导入声明-Java 24 讨论了以下要点:
- 工作原理?
- 使用模块导入语句时如何处理歧义?
- Java 模块系统中的传递性依赖
- java.base 的隐式可用性
- 显式要求 java.se
JEP 505:结构化并发(第五版预览)
何谓结构化并发?
结构化并发是一种范式,它将相关的并发任务视为具有明确定义动态作用域的单一工作单元。Java中的主要API是StructuredTaskScope,它确保:
- 子任务的生命周期受限于代码块的词法作用域(通常为try-with-resources语句)。
- 错误处理、结果收集和取消操作均以清晰方式协调执行。
- 提升了中断的可观察性和传播性。
这与“非结构化”线程管理(如ExecutorService、CompletableFuture)形成鲜明对比——后者中任务生命周期往往难以追踪,错误/取消操作可能静默传播或丢失。
为何采用结构化并发?
- **简化错误处理:**若任何子任务失败,其余任务将自动取消。
- **生命周期清晰:**所有子任务在单一代码块内启动并终止,杜绝线程/资源泄漏。
- **协调式取消:**父作用域中断将传播至所有子任务。
- **组合式设计:**所有任务结果均可获取,或统一抛出集体失败异常。
结构化并发在历代JDK版本中的演进历程
结构化并发功能历经多个JDK版本发展:
- 始于JDK 19和JDK 20的孵化功能阶段。
- 在JDK 21进入预览阶段,此时fork方法的返回类型从Future改为Subtask。
- 该功能在JDK 22、23和24版本中始终处于预览状态。
在JDK 25版本中,该功能作为另一项预览功能提出,并进行了关键API改进。最显著的变化是,StructuredTaskScope对象现将通过静态工厂方法创建。基础的零参数open()工厂方法适用于常见场景:等待所有子任务完成或检测子任务失败。针对更复杂的策略,开发者可使用接受Joiner参数的其他工厂方法自定义结果处理方式。
示例:
import java.util.concurrent.StructuredTaskScope;
public Response handle() throws InterruptedException {
try (var scope = StructuredTaskScope.open()) {
var user = scope.fork(() -> findUser());
var order = scope.fork(() -> fetchOrder());
scope.join(); // Waits for both, propagates exceptions
// Both succeeded
return new Response(user.get(), order.get());
}
}
若findUser()或fetchOrder()任一任务失败(抛出异常),另一任务将被取消并传播错误。所有资源在退出try代码块时均保证被清理。
JEP 505 提出的结构化并发机制通过将子任务划分为清晰的生命周期并一致传播错误/取消事件,使 Java 能够实现安全、可读且易维护的并行代码。StructuredTaskScope API 是构建此类模式的核心工具,能显著简化 Java 并发代码并降低错误率。
JEP 506:作用域值
作用域值 API 由 JEP 429(JDK 20)提出孵化,经 JEP 446(JDK 21)进入预览阶段,随后通过 JEP 464(JDK 22)、JEP 481(JDK 23)及 JEP 487 (JDK 24)逐步完善。
现提议在JDK 25中最终确定作用域值API,仅作一项细微调整:ScopedValue.orElse方法不再接受null作为参数。
作用域值是什么?
作用域值是一种新型并发原语,允许代码在明确定义的词法作用域内,在调用方、被调用方和子线程之间共享不可变的上下文数据。与ThreadLocal不同,其生命周期、访问权限和可变性均受到语言运行时的严格约束与管理。
为何不使用 ThreadLocal?
- ThreadLocal 允许将可变上下文附加到线程,但上下文的生命周期不明确,存在内存泄漏或数据过时的风险。
- 除非被显式移除,ThreadLocal 值将持续存在于整个线程生命周期,这在使用虚拟线程、线程池或结构化并发环境中存在隐患。
作用域值可解决这些问题:
- 会话/上下文在代码块中自动由子线程继承。
- 无需手动移除或清理。值仅在绑定作用域内可访问。
- 值真正不可变,防止跨请求意外共享。
如何使用作用域值?
声明方式:
作用域值通常声明为 static final(类似 ThreadLocal),但仅能在特定作用域内读取或绑定。
private static final ScopedValue<UserContext> CTX = ScopedValue.newInstance();
**将值绑定到作用域:
**
使用 ScopedValue.where() 方法,并在 lambda 表达式中执行逻辑。
ScopedValue.where(CTX, userContext)
.run(() -> {
processRequest();
});
在 processRequest 方法中(包括子线程或子方法),均可访问该作用域的 CTX.get()。超出作用域时,调用 CTX.get() 将抛出异常。
示例:Web 框架中的上下文传播
使用范围值之前(采用ThreadLocal):
private static final ThreadLocal<FrameworkContext> CONTEXT = new ThreadLocal<>();
void serve(Request request, Response response) {
CONTEXT.set(createContext(request));
Application.handle(request, response);
CONTEXT.remove();
}
风险包括忘记清理、上下文泄漏以及生命周期混淆。
使用范围值后:
private static final ScopedValue<FrameworkContext> CONTEXT = ScopedValue.newInstance();
void serve(Request request, Response response) {
var context = createContext(request);
ScopedValue.where(CONTEXT, context).run(() -> {
Application.handle(request, response);
});
}
public PersistedObject readKey(String key) {
var context = CONTEXT.get(); // Read within scope
var db = getDBConnection(context);
return db.readKey(key);
}
- 在serve()中绑定的值仅可在.run()代码块内及该调用堆栈中调用的任何方法内读取。
- 若在 .run() 返回后调用 readKey(),CONTEXT.get() 将抛出异常。
- 无需手动移除该值。
演示ScopedValue.orElse()方法变更的示例
在Java 25中,ScopedValue.orElse方法进行了关键性最终化:不再允许其参数为null。若尝试向orElse传递null,将抛出NullPointerException异常。备用值必须始终为非空值。
抛出NullPointerException示例
import java.lang.ScopedValue;
public class ScopedValueDemo {
private static final ScopedValue<String> SCOPE = ScopedValue.newInstance();
public static void main(String[] args) {
// No binding for SCOPE in this thread
// This would previously be legal in preview, but now will throw NullPointerException
String fallback = null;
String value = null;
try {
value = SCOPE.orElse(fallback); // Throws NullPointerException in Java 25
} catch (NullPointerException e) {
System.out.println("Caught expected NullPointerException: fallback cannot be null.");
}
// Correct usage: always supply a non-null fallback
String safeValue = SCOPE.orElse("Default");
System.out.println("Safe fallback: " + safeValue);
}
}
在Java 25中,首次调用SCOPE.orElse(null)将抛出NullPointerException。正确用法是始终提供非空备用值,例如SCOPE.orElse(“Default”)。此API变更确保安全性和一致性,因此在Java 25中使用ScopedValue.orElse时必须始终提供非空回退值。若未提供,将抛出NullPointerException而非返回null。
正确示例:
private static final ScopedValue<String> SCOPED_USER = ScopedValue.newInstance();
public static void main(String[] args) {
// No binding exists for SCOPED_USER here
String result = SCOPED_USER.orElse("guest"); // "guest" is valid fallback
System.out.println(result); // Prints: guest
}
JEP 502:稳定值(预览版)
本JEP提出“稳定值”的预览API。稳定值是Java 25核心库功能,提供延迟不可变性的新API。
- 定义: 用于创建“稳定值”的新API,即数据不会改变的对象。
- 性能: 由于其值为常量,JVM会像优化final字段那样对其进行优化。
- 优势: 在值的赋值方式和时机上,它们比final字段更具灵活性。
- 目的: 将应用程序数据的大型单块初始化分解为更小、更高效的阶段,从而提升 Java 应用程序的启动性能。
- 状态: 本次发布中为预览版 API。
为何需要稳定值?
- 传统final字段必须进行热初始化(在构造或静态初始化阶段),这会拖慢大型应用的启动速度。
- 可变字段虽支持延迟初始化,但无法享受JVM优化,且可能因多重或不安全赋值引发错误。
- 稳定值 同时解决上述问题:允许延迟设置值(仅限一次),同时享受常量折叠和线程安全优势。
核心 API
- StableValue 是主要类。
- StableValue.of() 创建新的空稳定值。
- .orElseSet(Supplier) 提供原子操作:若值不存在则延迟设置,确保仅单线程成功。
示例:
import java.lang.StableValue;
public class OrderController {
// Deferred, immutable Logger—thread-safe, only set once!
private final StableValue<Logger> logger = StableValue.of();
public Logger getLogger() {
// If not already set, safely initialize it (lazily)
return logger.orElseSet(() -> Logger.create(OrderController.class));
}
}
首次调用通过供应商设置值,后续调用返回不可变的 Logger。
与延迟初始化的对比
旧方法(稳定值出现前):
private Logger logger = null;
Logger getLogger() {
if (logger == null) {
logger = Logger.create(OrderController.class);
}
return logger;
}
示例:###### 19首次调用通过供应商设置值,后续调用返回不可变的 Logger。### 与延迟初始化的对比旧方法(稳定值出现前):###### 20
非线程安全,日志器可能被重新赋值,JVM不进行常量折叠。
使用稳定值(Java 25):
private final StableValue<Logger> logger = StableValue.of();
Logger getLogger() {
return logger.orElseSet(() -> Logger.create(OrderController.class));
}
线程安全,仅初始化时赋值一次,JVM在初始化后将其视为常量。
高级示例:启动优化
假设应用中存在多个耗时控制器:
public class Application {
static final StableValue<OrderController> orders = StableValue.of();
static final StableValue<UserService> users = StableValue.of();
static OrderController getOrderController() {
return orders.orElseSet(OrderController::new);
}
}
OrderController(及UserService)仅在需要时构造。启动无延迟,并发访问完全安全;创建后不可变。
对比总结表
| Feature | final fields | Stable Values (Java 25) |
|---|---|---|
| Eager initialization | Required | Optional (deferred/lazy) |
| Immutable reference | Yes | Yes (once set) |
| JVM optimizations | Yes | Yes (after assignment) |
| Thread safety | Yes | Yes (atomic, at-most-once) |
| Startup delay | Possible | None (deferred) |
| Preview status | N/A | Yes |
优势与最佳实践
- 性能: 采用延迟初始化提升应用启动效率,无需一次性构建所有对象。
- 安全性: StableValue 确保最多仅赋值一次,即使在并发线程间亦然。
- 清晰度: API 明确标识哪些字段不可变但采用延迟初始化。
- 互操作性: JVM 运行时使用时会应用常量折叠优化,如同处理 final 字段一样。
JEP 510:密钥派生函数 API
本提案引入密钥派生函数(KDF)的标准 API。这些加密工具用于从现有密钥和附加数据生成新的安全密钥。
该 KDF API 最初作为预览功能引入于 JDK 24(通过 JEP 478)。现提议在 JDK 25 中将其作为永久功能最终确定,且与预览版本相比不作任何修改。
什么是密钥派生函数(KDF)?
密钥派生函数(KDF)是一种密码学基本组件,用于从主密钥(如密码、主密钥或共享密钥)派生一个或多个密钥。KDF在TLS协议、安全密码存储及后量子密码学方案中至关重要。它们通过初始密钥材料、盐值及可选上下文信息等输入,生成具有密码学强度的密钥。
密钥类与方法
- javax.crypto.KDF:表示KDF算法的主类。
- KDF.getInstance(String algorithm):为特定算法实例化KDF,例如“HKDF-SHA256”。
- KDF.deriveKey(String algorithm, AlgorithmParameterSpec spec):为指定算法派生密钥。
- KDF.deriveData(AlgorithmParameterSpec spec):派生字节数组数据(熵值、密钥材料)。
示例:
KeyDerivationFunction kdf = KeyDerivationFunction.create("HKDF");
SecretKey derived = kdf.deriveKey(originalKey, salt, info);
JEP 470:加密对象的PEM编码(预览版)
本提案为处理增强隐私邮件(PEM)格式提供全新预览API。开发者可借此将安全对象(如密钥和证书)编码为PEM文本,并将其反编码为对应的Java对象。
该功能的核心目标是创建简洁高效的API,实现PEM编码数据与其表示对象之间的转换,显著降低开发者的操作难度。
什么是PEM?
增强隐私邮件格式(PEM)是一种广泛使用的基于文本的格式,用于编码证书、公钥和私钥等加密对象。PEM文件采用Base64编码的二进制数据,并包裹在可读的头部和尾部行中,例如:
-----BEGIN CERTIFICATE-----
...Base64 encoded data...
-----END CERTIFICATE-----
PEM是TLS/SSL证书、SSH密钥及众多安全工具中广泛采用的标准格式。
JEP 508:向量API(第十孵化器)
JEP 508定义的Java 25向量API(第十孵化器)是一个不断演进的强大接口,支持Java开发者编写高性能、可移植且易读的向量化代码,充分利用SIMD硬件能力,显著提升多领域计算速度。相较传统标量(非向量)代码,其性能表现更具优势。
向量 API 自 JDK 16 起作为孵化功能历经多次 JDK 版本迭代,并在后续版本(至 JDK 24)中持续更新。
现提议在 JDK 25 中延续其孵化进程,并引入多项关键改进:
- API增强: VectorShuffle现可直接处理堆外内存(MemorySegment)中的数据。
- 可维护性提升: 内部实现现采用标准外部函数与内存API调用数学库,取代JVM内部复杂的定制代码,从而简化代码维护。
- 新增硬件支持: 在兼容的x64 CPU上,针对Float16值的运算(如加法和乘法)现可自动通过向量指令进行优化。
该API将保持孵化状态,直至Project Valhalla的基础功能就绪。届时Vector API将适配这些功能并进入预览阶段。
JEP 519: 紧凑对象头
紧凑对象头最初在JDK 24作为标准对象头布局的实验性替代方案引入。这种谨慎策略是大型功能的标准做法,可确保充分测试。
JEP 519将紧凑对象头提升为Java 25的一流生产级功能,显著改善Java应用程序的内存使用和运行时性能,尤其适用于包含大量小型对象的场景。此增强与Lilliput项目目标一致,旨在大幅降低Java内存占用。
在64位JVM上,对象头从128位缩减至64位,显著减少内存消耗并提升性能,尤其适用于部署大量小型对象的场景。
JEP 521:代际 Shenandoah
代际 Shenandoah 技术已在 JDK 24(JEP 404)中进行实验性引入。JDK 25 将其正式升级为产品级特性,无需再使用实验性 JVM 标志。
Shenandoah 是一种低停顿并发垃圾收集器,通过在运行 Java 线程的同时执行大部分工作,旨在最大限度减少传统的“停止世界”停顿。它针对大型堆内存和延迟敏感型应用程序,停顿时间始终低于 10 毫秒。
代际 Shenandoah 通过引入代际垃圾收集支持扩展了 Shenandoah,根据对象年龄将堆内存对象分隔:
- 幼代:近期创建且通常很快不可达的对象。
- 老代:经多次回收仍存活的长寿命对象。
该设计遵循弱代假说——即多数对象在幼代阶段即被回收。
升级版垃圾回收器提供更短暂停时间与更优内存管理。
适用场景:大规模、对延迟敏感的应用程序。
JEP 514:前置编译命令行优化
前置编译(Ahead-of-Time)可在运行前将部分Java字节码编译为本地代码,通过避免应用启动时的即时编译(JIT)工作来缩短启动时间。
Java 24引入了基于应用负载记录AOT缓存的功能,通过预加载和链接类实现后续运行加速。
Java 25的JEP 514引入-XX:AOTCacheOutput命令行选项,将两个阶段整合为单次JVM调用,实现:
- 运行应用程序一次,将类加载行为记录到内部临时文件中。
- 创建由 -XX:AOTCacheOutput 选项指定的 AOT 缓存文件。
- 自动清理临时文件。
示例:
java -XX:AOTCacheOutput=app.aot -cp app.jar MainClass
将原先两步流程简化为单条命令。
JEP 515:提前方法剖析
提前方法剖析是Java 25引入的功能,可在应用程序训练运行期间收集方法执行剖析数据,并将这些剖析数据存储于AOT缓存中。该剖析数据包含方法执行频率统计、典型对象类型及其他运行时行为信息,有助于JVM的即时编译器(JIT)在启动时更高效地优化代码。
预先方法剖析允许在启动时利用先前训练运行生成的预存执行剖析数据初始化JVM,从而加速热点检测和JIT优化阶段。
JEP 503:移除32位x86端口
JEP 503移除了OpenJDK中HotSpot JVM的32位x86(Intel/AMD)端口源代码及构建支持。该端口已在JDK 24(JEP 501)中弃用,并于JDK 25中完全移除。
移除内容
- 专属于 x86 32 位架构的源文件。
- 用于 32 位 x86 编译的构建脚本和配置。
- 仅在 32 位 x86 上运行的测试。
- 该平台专属的兼容性与回退代码。
仍受支持的平台
- 其他32位平台(如ARM32)仍受支持。
- 64位x86(x86-64/AMD64)仍是英特尔/AMD硬件的主要支持方向。
- 零端口模式(一种架构无关的解释器模式)仍可用,但不包含即时编译优化。
对开发者的影响
- 在64位系统上运行的应用程序不会察觉差异。
- 运行32位x86 JVM的传统用户应考虑迁移至64位JVM。
- Zero解释器仍可在不受支持的硬件上使用,但性能会下降。
JEP 509:JFR CPU时间剖析
Java飞行记录器(JFR)是JVM内置的剖析与诊断工具。传统上,JFR通过采集执行时间样本近似估算CPU使用率,该机制以固定间隔采集真实时间流逝的堆栈跟踪样本。
JEP 509 在 Linux 平台引入实验性 CPU 时间剖析功能,基于 CPU 消耗时间而非经过时间捕获线程堆栈样本,显著提升 CPU 使用率剖析的精度。
JEP 518:JFR 协作采样
Java Flight Recorder(JFR)通过在任意点暂停线程来异步采样Java线程堆栈,从而收集堆栈跟踪信息。这种异步采样机制在线程未处于明确安全状态时,会运用启发式算法遍历线程堆栈。
JEP 518通过在JVM安全点采用协作式采样机制,重构了JFR采样机制,从而提升了稳定性和可扩展性。
JEP 520:JFR 方法计时与追踪
JFR(Java Flight Recorder)方法计时与追踪通过对字节码进行仪器化,提供了增强功能以精确记录特定 Java 方法的执行时间和追踪信息。这些功能通过提供精确的方法级统计数据(包括调用次数和持续时间)改进了传统采样方式。
JEP 520 显著增强了 JFR 为开发者提供详细方法级计时与跟踪信息的能力,在最大限度减少应用程序变更和开销的同时,赋予强大的性能洞察与故障排查能力。
Java 25 新特性完整 JEP 列表(附示例)
| JEP | Feature | Status | Category |
|---|---|---|---|
| 470 | PEM Encodings of Cryptographic Objects | Preview | Security |
| 502 | Stable Values | Preview | Core Libs |
| 503 | Remove the 32-bit x86 Port | Final | Removal |
| 505 | Structured Concurrency | Fifth Preview | Concurrency |
| 506 | Scoped Values | Final | Concurrency |
| 507 | Primitive Types in Patterns, instanceof, and switch | Third Preview | Syntax |
| 508 | Vector API | Incubator | Performance |
| 509 | JFR CPU-Time Profiling | Experimental | Profiling |
| 510 | Key Derivation Function API | Final | Security |
| 511 | Module Import Declarations | Final | Syntax |
| 512 | Compact Source Files and Instance Main Methods | Final | Syntax |
| 513 | Flexible Constructor Bodies | Final | Syntax |
| 514 | Ahead-of-Time Command-Line Ergonomics | Final | Performance |
| 515 | Ahead-of-Time Method Profiling | Final | Performance |
| 518 | JFR Cooperative Sampling | Final | Profiling |
| 519 | Compact Object Headers | Final | Performance |
| 520 | JFR Method Timing & Tracing | Final | Profiling |
| 521 | Generational Shenandoah | Final | Garbage Collector |
结语
Java 25 的改进使学习与专业发展更轻松高效。紧凑型程序助力新手快速入门,并发性、性能及安全性的增强则为资深开发者带来更稳健、可扩展的应用程序。若需深入技术细节,请查阅各功能对应的 JEP 文档。Java 的演进始终保持高速,使其持续位居当今全球最具影响力的编程语言之列。
来源:
你也许感兴趣的: