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)returns- trueif the content was set to- tor- falseif the content was already set
- setOrThrow(T t)sets the content to- t, otherwise throws an exception if the content was already set
- orElse(T t)returns the content (if set), otherwise returns- t
- orThrow()returns the content (if set), otherwise throws- NoSuchElementException
- isSet()returns if the content is set.
- orElseSet(Supplier<? extends T> s)returns the content, otherwise computes a value using- sand initializes the content accordingly (which is then returned)
The StableValue interface also contains seven static factories:
- StableValue.of(), creates a new unset- StableValuewith no content.
- StableValue.of(T value), creates a new set- StableValuewith the provided content.
- StableValue.supplier(Supplier<? extends T> s), creates a- Supplier<T>that caches the value of- s(the latter is invoked at most once) in an internal- StableValue
- StableValue.intFunction(int size, IntFunction<? extends R> m)creates an- IntFunction<R>with allowed [0..size) inputs that caches the values produced by- min an internal array of- StableValueelements
- StableValue.function(Set<T> inputs, Function<T, R> m)creates a- Function<T, R>with allowed- inputsthat caches the values produced by- min an internal array of- StableValueelements.
- StableValue.list(int size, IntFunction<? extends R> m). Similar to- intFunction()but returns a completely lazy- List<R>.
- StableValue.map(Set<T> inputs, Function<T, R> m). Similar to- function()but returns a completely lazy- Map<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-8351565 Implement JEP 502: Stable Values (Preview) -           
- Resolved
 
-         
- 
                    JDK-8342067 Implement JEP 8312611: Stable Values (Preview) -           
- Closed
 
-         
- relates to
- 
                    JDK-8366179 Implement JEP 526: Lazy Constants (Second Preview) -           
- Provisional
 
-