InfoQ Homepage News Java 25 Introduces Stable Values API for Deferred Immutability and Improved Application Startup
Java 25 Introduces Stable Values API for Deferred Immutability and Improved Application Startup
Jun 02, 2025 2 min read
Write for InfoQ
Feed your curiosity. Help 550k+ globalsenior developers
each month stay ahead.Get in touch
JEP 502, Stable Values (Preview), has been moved to Completed status for JDK 25. Formerly known as Computed Constants (Preview), this JEP introduces the concept of computed constants, defined as immutable value holders that are initialized at most once. The new API allows developers to create objects with "deferred immutability." These objects can be initialized once at any point during execution and remain immutable thereafter, combining the performance benefits of final fields with the flexibility of lazy initialization.
The Stable Values API specifically targets application startup performance issues caused by eager initialization of complex objects. Unlike final fields, which must be initialized during construction or class initialization, stable values can be initialized on-demand while also enabling JVM constant-folding optimizations typically reserved for final fields. This is still a Preview feature.
The Stable Values API centers around the StableValue class, which holds a single data value that can be set exactly once. The primary initialization method, orElseSet(), ensures thread-safe, at-most-once initialization even under concurrent access:
class OrderController {
private final StableValue<Logger> logger = StableValue.of();
Logger getLogger() {
return logger.orElseSet(() -> Logger.create(OrderController.class));
}
}
This approach eliminates common pitfalls associated with traditional lazy initialization patterns. Without stable values, developers typically resort to mutable fields with null-checking, which prevents JVM optimizations and introduces thread safety concerns:
// Traditional approach - loses optimization opportunities
class OrderController {
private Logger logger = null; // Mutable field
Logger getLogger() {
if (logger == null) {
logger = Logger.create(OrderController.class);
}
return logger;
}
}
The API extends beyond basic stable values to include stable suppliers and stable lists. Stable suppliers allow initialization logic to be specified at declaration time while deferring actual execution:
class DataService {
private final Supplier<DatabaseConnection> connection =
StableValue.supplier(() -> new DatabaseConnection("jdbc:postgresql://localhost/db"));
void performQuery() {
DatabaseConnection db = connection.get();
// Database connection created only on first access
}
}
Stable lists support collections where individual elements are initialized independently as accessed:
class ThreadPool {
private final List<WorkerThread> workers =
StableValue.list(POOL_SIZE, index -> new WorkerThread(index));
WorkerThread getWorker(int index) {
return workers.get(index); // Worker created only when first accessed
}
}
The key advantage of stable values lies in their treatment by the JVM. Under the hood, stable values use the JDK-internal @Stable annotation, which signals to the JVM that, despite being stored in a non-final field, the value will not change after its initial update. This enables the same constant-folding optimizations available to final fields.
Stable values enable a fundamental rethinking of application initialization strategies. Applications can now defer the creation of expensive components until they are actually needed, dramatically improving startup times:
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);
}
}
This pattern allows applications to start instantly, with components initialized on demand as the application's execution path requires them. The approach is particularly beneficial for large enterprise applications with numerous components, many of which may not be used during typical execution.
As a preview API, Stable Values require explicit enablement during compilation and runtime:
javac --release 25 --enable-preview MyApplication.java
java --enable-preview MyApplication
The preview status allows the development team to gather feedback from the Java community before finalizing the API design and implementation.
The Stable Values API in Java 25 offers a compelling solution to long-standing initialization challenges, providing developers with a tool that combines the safety and performance of immutable fields with the flexibility of lazy initialization.
This content is in the Java topic
Related Topics:
-
Related Editorial
-
Related Sponsors
-
Popular across InfoQ
-
AWS Introduces ECS Managed Instances for Containerized Applications
-
Producing a Better Software Architecture with Residuality Theory
-
GitHub Introduces New Embedding Model to Improve Code Search and Context
-
Google DeepMind Introduces CodeMender, an AI Agent for Automated Code Repair
-
Building Distributed Event-Driven Architectures across Multi-Cloud Boundaries
-
Mental Models in Architecture and Societal Views of Technology: A Conversation with Nimisha Asthagiri
-
Related Content
The InfoQ Newsletter
A round-up of last week’s content on InfoQ sent out every Tuesday. Join a community of over 250,000 senior developers. View an example