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
