Stable values
Thread-safe lazy initialization without volatile or synchronized.
Code Comparison
✕ Java 8
private volatile Logger logger;
Logger getLogger() {
if (logger == null) {
synchronized (this) {
if (logger == null)
logger = createLogger();
}
}
return logger;
}
✓ Java 25 (Preview)
private final StableValue<Logger> logger =
StableValue.of(this::createLogger);
Logger getLogger() {
return logger.get();
}
Why the modern way wins
Zero boilerplate
No volatile, synchronized, or null checks.
JVM-optimized
The JVM can fold the value after initialization.
Guaranteed once
The supplier runs exactly once, even under contention.
Old Approach
Double-Checked Locking
Modern Approach
StableValue
Since JDK
25
Difficulty
advanced
JDK Support
Stable values
Available
Preview in JDK 25 (JEP 502). Requires --enable-preview.
How it works
StableValue provides a lazily initialized, immutable value with built-in thread safety. No double-checked locking, no volatile fields, no synchronized blocks. The JVM can even optimize the read path after initialization.