Summary
Introduce an API for stable values, which are objects that hold immutable data. Stable values are treated as constants by the JVM, enabling the same performance optimizations that are enabled by declaring a field final. Compared to final fields, however, stable values offer greater flexibility as to the timing of their initialization.
This CSR refers to the first iteration of the Stable Value API to make the API available as a Preview API.
Problem
There is a tension between final
immutable fields and their mutable counterparts. Immutable fields must be initialized exactly once in the constructor or static initializer and can enjoy constant folding. Mutable fields can change at any time over and over again and hence, cannot be trusted by the VM to not change. There are a number of attempted workarounds using double-checked locking, concurrent maps, etc. but none of them provides constant folding.
Solution
Introduce the Stable Values API, which adds support for stable values. Stable values can be initialized from anywhere in the code, by any thread, and at any time. Yet, if set, they can be constant-folded. A stable value is an immutable holder of content of type T.
The StableValue interface contains six methods:
trySet(T t)
returnstrue
if the content was set tot
orfalse
if the content was already setsetOrThrow(T t)
sets the content tot
, otherwise throws an exception if the content was already setorElse(T t)
returns the content (if set), otherwise returnst
orThrow()
returns the content (if set), otherwise throwsNoSuchElementException
isSet()
returns if the content is set.orElseSet(Supplier<? extends T> s)
returns the content, otherwise computes a value usings
and initializes the content accordingly (which is then returned)
The StableValue interface also contains seven static factories:
StableValue.of()
, creates a new unsetStableValue
with no content.StableValue.of(T value)
, creates a new setStableValue
with the provided content.StableValue.supplier(Supplier<? extends T> s)
, creates aSupplier<T>
that caches the value ofs
(the latter is invoked at most once) in an internalStableValue
StableValue.intFunction(int size, IntFunction<? extends R> m)
creates anIntFunction<R>
with allowed [0..size) inputs that caches the values produced bym
in an internal array ofStableValue
elementsStableValue.function(Set<T> inputs, Function<T, R> m)
creates aFunction<T, R>
with allowedinputs
that caches the values produced bym
in an internal array ofStableValue
elements.StableValue.list(int size, IntFunction<? extends R> m)
. Similar tointFunction()
but returns a completely lazyList<R>
.StableValue.map(Set<T> inputs, Function<T, R> m)
. Similar tofunction()
but returns a completely lazyMap<T, R>
.
Specification
See attachment sv-diff4.txt
. For convenience, there is an HTML archive of the StableValue docs attached as well (
HTML4)
- csr of
-
JDK-8342067 Implement JEP 8312611: Stable Values (Preview)
-
- Open
-
-
JDK-8351565 Implement JEP 502: Stable Values (Preview)
-
- Open
-