RFR: 8351565: Implement JEP 502: Stable Values (Preview)
Luca Kellermann
duke at openjdk.org
Thu Mar 13 11:20:13 UTC 2025
On Mon, 10 Mar 2025 18:11:23 GMT, Per Minborg <pminborg at openjdk.org> wrote:
> Implement JEP 502.
>
> The PR passes tier1-tier3 tests.
src/java.base/share/classes/java/lang/StableValue.java line 79:
> 77: * logger.trySet(Logger.create(Component.class));
> 78: * }
> 79: * return logger.orThrow();
Suggestion:
* return logger.orElseThrow();
src/java.base/share/classes/java/lang/StableValue.java line 127:
> 125: * evaluated only once, even when {@code logger.orElseSet()} is invoked concurrently.
> 126: * This property is crucial as evaluation of the supplier may have side effects,
> 127: * e.g., the call above to {@code Logger.getLogger()} may result in storage resources
Suggestion:
* e.g., the call above to {@code Logger.create()} may result in storage resources
src/java.base/share/classes/java/lang/StableValue.java line 344:
> 342: * {@linkplain java.lang.ref##reachability reachable} stable values will hold their set
> 343: * content perpetually.
> 344: * <p>
Should the original functions / mappers (for stable functions and collections) also stay reachable? Kotlin's [`Lazy`](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-lazy/) [nulls out](https://github.com/JetBrains/kotlin/blob/c6f337283d59fcede75954eebaa589ad1b479aea/libraries/stdlib/jvm/src/kotlin/util/LazyJVM.kt#L70-L89) the initializer function when it's no longer needed.
src/java.base/share/classes/java/lang/StableValue.java line 423:
> 421: * {@snippet lang=java:
> 422: * if (stable.isSet()) {
> 423: * return stable.get();
Suggestion:
* return stable.orElseThrow();
src/java.base/share/classes/java/lang/StableValue.java line 547:
> 545: IntFunction<? extends R> original) {
> 546: if (size < 0) {
> 547: throw new IllegalArgumentException();
This exceptions isn't documented, same for `StableValue.list()`
src/java.base/share/classes/jdk/internal/lang/stable/StableEnumFunction.java line 112:
> 110: final Class<E> enumType = (Class<E>)inputs.iterator().next().getClass();
> 111: return (Function<T, R>) new StableEnumFunction<E, R>(enumType, min, StableValueFactories.array(size), (Function<E, R>) original);
> 112: }
If `inputs` contains the enumuration constants with ordinals 0 and 2, wouldn't this code wrongly cause the enumeration constant with ordinal 1 to be an allowed input?
src/java.base/share/classes/jdk/internal/lang/stable/StableValueImpl.java line 141:
> 139: ? "(this StableValue)"
> 140: : "StableValue" + renderWrapped(t);
> 141: }
Are deeper cycles of concern? I was thinking of this:
var a = StableValue.of();
var b = StableValue.of();
a.trySet(b);
b.trySet(a);
System.out.println(a);
This would solve deeper cycles for `StableValueImpl`:
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("StableValue");
int depth = 0;
Object t = value;
while (t instanceof StableValueImpl<?> s) {
if (s == this) {
t = "(this StableValue)";
break;
}
sb.append("[StableValue");
depth++;
t = s.value;
}
sb.append(renderWrapped(t));
while (depth-- > 0) sb.append(']');
return sb.toString();
}
This might also apply to stable functions and collections, I haven't thought it through for them.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r1989143787
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r1989165612
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r1989265489
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r1989377859
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r1989504117
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r1988064795
PR Review Comment: https://git.openjdk.org/jdk/pull/23972#discussion_r1988092230
More information about the core-libs-dev
mailing list