写点什么

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:044033

评论

发布
暂无评论

原子性操作类的使用

武哥聊编程

Java 多线程 原子性 28天写作

每个人都应该理解这三个基本的 MLOps 概念

李忠良

28天写作

Webpack | 如何提升构建速度,进行体积优化?

梁龙先森

大前端 webpack 28天写作 2月春节不断更

深入理解nodejs的HTTP处理流程

程序那些事

node.js HTTP 异步编程 程序那些事

图解 | 原来这就是线程池

架构 线程池

黑客练手入门| pwnable.kr—幼儿瓶—01:fd

BigYoung

黑客 安全 安全漏洞 28天写作 2月春节不断更

第四周-第一课

Geek_娴子

管理笔记[6]:任人唯贤、赏罚分明、任人所长

L3C老司机

信息茧房

lidaobing

28天写作 信息茧房

SpringIOC的注解开发

小马哥

Java spring 七日更

如果生命的长度可以被改写「幻想短篇 27/28」

道伟

28天写作

日记 2021年2月3日(周三)

Changing Lin

个人感悟 2月春节不断更

28天瞎写的第二百三十七天:抢了HR 饭碗了吗?

树上

HR 28天写作

十倍效率背后的管理逻辑

Ian哥

28天写作

你会在车里唱K吗? (28天写作 Day27/28)

mtfelix

28天写作 智能汽车 MaaS 出行方案

通过扫码提交信息

IT蜗壳-Tango

七日更 2月春节不断更

Mybatis【18】-- Mybatis自关联多对一查询方式

秦怀杂货店

mybatis

常用网址

现实中游走

Redis缓存热点引发的思考

Java架构师迁哥

硬核!阿里自爆虐心万字面试手册,Github上获赞89.7K

996小迁

spring 架构 面试 程序人生 JVM

驱动力读书笔记之三

张老蔫

28天写作

让我们与内心聊聊,寻找一段思考发展之路。

叶小鍵

人员培养,不是捷径的捷径(下)

一笑

管理 人才培养 28天写作

思维导图整理Java并发基础

Java 架构 并发

回顾与总结 | 视频号28天(28)

赵新龙

28天写作

信任从对自己诚实开始

Justin

心理学 信任 28天写作

机器学习笔记之:Addition and Scalar Multiplication

Nydia

为什么要持续学习

不在调上

分析 BAT 互联网巨头在大数据方向布局及大数据未来发展趋势

五分钟学大数据

大数据 2月春节不断更

Mac打开wps后风扇转的快机身发热

现实中游走

Mac cpu 100% wps 机身发热

【Linux系统】常驻进程应用实践

程序员架构进阶

Linux 守护进程 七日更 28天写作 2月春节不断更

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