写点什么

Java 25 为延迟不可变性引入了稳定值 API,并改进了应用程序启动

  • 2025-06-03
    北京
  • 本文字数:1629 字

    阅读完需:约 5 分钟

大小:467.59K时长:02:39
Java 25为延迟不可变性引入了稳定值API,并改进了应用程序启动

JEP 502,稳定值(预览版),在 JDK 25 中已移动到完成状态。这个 JEP 以前称为计算常量(预览版),它引入了计算常量的概念,被定义为最多初始化一次的不可变值持有者。新的 API 允许开发人员创建具有“延迟不可变性”的对象。这些对象可以在执行过程中的任何时候被初始化一次,然后保持不可变性,结合了 final 字段的性能优势和延迟初始化的灵活性。

 

稳定值 API 专门针对由复杂对象过早初始化而引起的应用程序启动性能问题。与必须在构造或类初始化期间初始化的 final 字段不同,稳定值可以按需初始化,同时还启用了 JVM 常量折叠优化。这些优化通常只适用于 final 字段。不过这仍然是一个预览功能

 

稳定值 API 围绕StableValue类展开,该类持有一个只能精确设置一次的数据值。主要的初始化方法orElseSet()可确保即使在并发访问 的情况下也能进行线程安全的至多一次初始化:

 

class OrderController {    private final StableValue<Logger> logger = StableValue.of();    Logger getLogger() {        return logger.orElseSet(() -> Logger.create(OrderController.class));    }}
复制代码

 

这种方法消除了与传统延迟初始化模式相关的常见陷阱。如果没有稳定的值,开发人员通常会使用带有 null 检查的可变字段,这会阻碍 JVM 优化,并会引入线程安全问题:

 

// 传统方法 - 失去了优化机会class OrderController {    private Logger logger = null; // 可变字段    Logger getLogger() {        if (logger == null) {            logger = Logger.create(OrderController.class);        }        return logger;    }}
复制代码

 

API 不能扩展了基本的稳定值,还包括稳定的供应商(supplier)和稳定的列表(list)。稳定的供应商允许在声明时指定初始化逻辑,同时延迟实际执行:

 

class DataService {    private final Supplier<DatabaseConnection> connection = StableValue.supplier(() -> new DatabaseConnection("jdbc:postgresql://localhost/db"));    void performQuery() {        DatabaseConnection db = connection.get(); // 数据库连接仅在首次访问时创建    }}
复制代码

 

稳定列表支持集合,其中各个元素在访问时单独初始化:

 

class ThreadPool {    private final List<WorkerThread> workers = StableValue.list(POOL_SIZE, index -> new WorkerThread(index));    WorkerThread getWorker(int index) {        return workers.get(index); // 仅在首次访问时创建工作线程    }}
复制代码

 

稳定值的关键优势在于 JVM 处理它们的方式。在底层,稳定值使用 JDK 内部的 @Stable 注解,它告诉 JVM,尽管存储在非 final 字段中,但值在初始更新后不会改变。这使得 final 字段可以使用相同的常量折叠优化。

 

稳定值使得从根本上重新考虑应用程序的初始化策略成为可能。现在,应用程序可以将昂贵组件的创建推迟到真正需要时,从而显著改善了启动时间:

 

class Application {    static final StableValue<OrderController> orders = StableValue.of();    static final StableValue<UserService> users = StableValue.of();    public static OrderController getOrderController() {        return orders.orElseSet(OrderController::new);    }}
复制代码

 

这种模式允许应用程序立即启动,并根据应用程序的执行路径需要按需初始化组件。这种方法特别适用于具有大量组件的大型企业应用程序,其中许多组件在典型的执行过程中可能不会被使用。

 

作为一个预览 API,稳定值需要在编译和运行时显式启用:

 

javac --release 25 --enable-preview MyApplication.javajava --enable-preview MyApplication
复制代码

 

预览状态允许开发团队在最终确定 API 设计和实现之前,从 Java 社区收集反馈。

 

Java 25 中的稳定值 API 为长期存在的初始化挑战提供了一个引人注目的解决方案,它为开发人员提供了一个工具,将不可变字段的安全和性能与延迟初始化的灵活性结合了起来。

 

原文链接:

https://www.infoq.com/news/2025/06/java25-stable-values-api-startup/

2025-06-03 10:045330

评论

发布
暂无评论

全网唯一秃头数据集:20 万张人像,网罗各类秃头

神经星星

人工智能 程序员 人脸识别 科技互联网

第二周总结

andy

极客大学架构师训练营第一天作业

Ethan

架构师训练营第二周总结

王铭铭

基于docker部署的Java应用jmx无法远程访问的问题

qihuajun

杜克大学提出 AI 算法,拯救渣画质马赛克秒变高清

神经星星

人工智能 算法 分辨率 GAN

架构师培训 -02 面向对象基本设计原则

刘敏

编程的本质

陈皮

Architecture Programing

面向对象设计学习总结

周冬辉

构架师训练营-第二周总结

Dawn

极客大学架构师训练营

架构师训练营第二次作业0616

Geek_10

第二周作业

新世界

架构

Week2学习总结

Frank Zeng

架构师week2 作业

李锦

极客大学架构师训练营

依赖倒置及Cache重构设计

架构5班杨娟Jessie

极客大学架构师训练营

GitHub 热榜:适合初学者学习的 Prometheus 监控系统

JackTian

GitHub 开源 运维 Prometheus 监控系统

架构师训练营 week2

devfan

设计模式

第二周总结

王锟

极客大学架构师训练营第一天总结

Ethan

架构训练营-第二节

刘志刚

架构师训练营第二周课后作业三

不谈

极客大学架构师训练营

ElasticSearch原理解析

elasticsearch

架构师训练营Week2

Frank Zeng

领域驱动设计(DDD)学习笔记

DDD

架构师训练营week2 学习小结

李锦

架构师训练营-第二周作业

Linuxer

极客大学架构师训练营

架构师训练营第二周作业

王铭铭

对进入面向对象世界的思考

云飞

UML 面向对象设计原则

教程序员使用Jekyll搭建漂亮的个人博客

小傅哥

小傅哥 Jekyll GitHub Pages 个人博客

架构师训练营第二周学习总结

James-Pang

极客大学架构师训练营

架构师训练营第二周学习总结

不谈

极客大学架构师训练营

Java 25为延迟不可变性引入了稳定值API,并改进了应用程序启动_编程语言_A N M Bazlur Rahman_InfoQ精选文章