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)returnstrueif the content was set totorfalseif 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 returnstorThrow()returns the content (if set), otherwise throwsNoSuchElementExceptionisSet()returns if the content is set.orElseSet(Supplier<? extends T> s)returns the content, otherwise computes a value usingsand initializes the content accordingly (which is then returned)
The StableValue interface also contains seven static factories:
StableValue.of(), creates a new unsetStableValuewith no content.StableValue.of(T value), creates a new setStableValuewith 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 internalStableValueStableValue.intFunction(int size, IntFunction<? extends R> m)creates anIntFunction<R>with allowed [0..size) inputs that caches the values produced bymin an internal array ofStableValueelementsStableValue.function(Set<T> inputs, Function<T, R> m)creates aFunction<T, R>with allowedinputsthat caches the values produced bymin an internal array ofStableValueelements.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-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)
-
- Closed
-