On Sat, 4 Oct 2025 14:29:08 GMT, ExE Boss <[email protected]> wrote:

>> Implement JEP 526: Lazy Constants (Second Preview)
>> 
>> The lazy list/map implementations are broken out from `ImmutableCollections` 
>> to a separate class.
>> 
>> The old benchmarks are not moved/renamed to allow comparison with previous 
>> releases.
>> 
>> `java.util.Optional` is updated so that its field is annotated with 
>> `@Stable`.  This is to allow `Optional` instances to be held in lazy 
>> constants and still provide constant folding.
>
> Getting access to the underlying `StableValue` API with **Lazy Constants** is 
> way too hacky and convoluted (but doable):
> <details>
> <summary>StableVar.java</summary>
> 
> 
> /*
>  * Any copyright is dedicated to the Public Domain.
>  * https://creativecommons.org/publicdomain/zero/1.0/
>  */
> 
> import java.util.NoSuchElementException;
> import java.util.function.Supplier;
> 
> import org.jspecify.annotations.NullMarked;
> import org.jspecify.annotations.Nullable;
> 
> import static java.lang.System.identityHashCode;
> import static java.util.Objects.requireNonNull;
> 
> /// Horrible awful hack to get access to raw stable values in JDK 26+.
> @NullMarked
> public sealed interface StableVar<T> permits StableHacks.StableVarImpl {
>       boolean trySet(final T contents) throws NullPointerException, 
> IllegalStateException;
>       @Nullable T orNull();
>       T orElse(final T other) throws NullPointerException;
>       T orElseThrow() throws NoSuchElementException;
>       boolean isSet();
>       T orElseSet(final Supplier<? extends T> supplier) throws 
> NullPointerException, IllegalStateException;
>       void setOrThrow(final T contents) throws NullPointerException, 
> IllegalStateException;
> 
>       static <T> StableVar<T> of() {
>               return StableHacks.newInstance();
>       }
> }
> 
> /// Encapsulates the actual implementation of `StableValue` on `LazyConstant`
> ///
> /// @author ExE Boss
> @NullMarked
> /*package*/ final @Namespace class StableHacks {
>       private StableHacks() throws InstantiationException { throw new 
> InstantiationException(StableHacks.class.getName()); }
> 
>       private static final String UNSET_SUFFIX = ".unset";
>       private static final Object UNSET = new Object() {
>               @Override
>               public int hashCode() {
>                       return 0;
>               }
> 
>               @Override
>               public String toString() {
>                       return "unset";
>               }
>       };
> 
>       private static final ScopedValue<?> SCOPE = ScopedValue.newInstance();
>       private static final Supplier<?> SCOPE_GETTER = SCOPE::get;
> 
>       /*package*/ static final <T> StableVarImpl<T> newInstance() {
>               return new StableValue<>();
>       }
> 
>       /*package*/ sealed interface StableVarImpl<T> extends StableVar<T> {
>       }
> 
>       private record StableValue<T>(
>               // Implemented as a record so that the JVM treats this as a 
> trusted final field
>               // even when `-XX:+TrustFinalNonStaticFields` is not set
>               LazyConstant<T> contents
>       ) implements StableVarImpl<T> {
>               @SuppressWarnings("unchecked")
>               private StableValue() {
>                       this(LazyConstant.<T>of((Supplier) SCOPE_GETTER));
>               }
> 
>               private StableValue {
>                       if (contents.isInitialized()) throw new InternalError();
>               }
> 
>               @SuppressWarnings("unchecked")
>               private fi...

Hi @ExE-Boss, this new JEP describes how this functionality will be provided in 
the future:

> Lazy constants cover the common, high-level use cases for lazy 
> initialization. In the future we might consider providing stable access 
> semantics directly, at a lower level, for reference, array, and primitive 
> fields. This would address, for example, use cases where the computing 
> function associated with a lazy constant is not known at construction.

This would be necessary, as there are usage patterns (such as nominal 
descriptors in ClassFile API) that would benefit from multiple assignment and a 
stable promoted read.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3368317631

Reply via email to