RFR: 8351565: Implement JEP 502: Stable Values (Preview) [v6]
John R Rose
jrose at openjdk.org
Sun Mar 16 03:13:00 UTC 2025
On Thu, 13 Mar 2025 15:22:43 GMT, Per Minborg <pminborg at openjdk.org> wrote:
>> Implement JEP 502.
>>
>> The PR passes tier1-tier3 tests.
>
> Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 246 commits:
>
> - Merge branch 'master' into implement-jep502
> - Clean up exception messages and fix comments
> - Rename field
> - Rename method and fix comment
> - Rework reenterant logic
> - Use acquire semantics for reading rather than volatile semantics
> - Add missing null check
> - Simplify handling of sentinel, wrap, and unwrap
> - Fix JavaDoc issues
> - Fix members in StableEnumFunction
> - ... and 236 more: https://git.openjdk.org/jdk/compare/4e51a8c9...d6e1573f
The example code `class Component` uses a `Supplier` non-static field to hold a singular stable value, in a lambda which does not capture `this`. It may be best not to claim a solution (yet) for lazy non-statics, so consider making `Component.logger` static.
I'm not saying you should attempt this in the present PR! But here are some related thoughts, for later.
Solving the problem of lazy statics, using stable suppliers, is a big deal. It allows single-static-holder-classes to be refactored more cheaply.
Here's why I think non-static lazy fields are not fully addressed by this PR. (A) Their initializer function should probably not capture `this`, for best performance, and (B) the VM's special casing of non-static fields of type `StableValue` does not extend to fields of type `Supplier`. (Nor should it.) But it seems we either need strict fields, or a JVM lockout of instance-supplier fields, to avoid problems with reflective object patching.
You might consider a type `StableSupplier` <: `Supplier` to address (B), but unless (A) is addressed as well there is not an efficient end-to-end solution for lazy non-statics.
(B) will also be addressed (independently) by strict statics.
A full solution might require an indexed version of Supplier (i.e., a restricted Function) which takes `this` whenever needed to evaluate the lazily supplied value. So there's some cross-connection with the design of stable functions in this PR.
(A stable function which caches one value seems useless, but it exactly fits the use case of a non-static lazy object attribute. The argument to the function is `this`. That's the only argument the instance-supplier will ever see. Every distinct instance of an instance-supplier will only ever see one instance of `this` as its argument value.)
class Component {
private strict final
StableInstanceSupplier<Compenent,Logger>
instanceSpecificLogger = StableValue.instanceSupplier(
self -> Logger.getLogger(Component.class, self.getName() );
}
In today's API you can get this effect but you have redundant bindings of `this` buried in the supplier structure. As other PR threads have pointed out, it's hard to drop the lambda after its invocation, so as to GC the storage of the bindings.
OTOH, maybe there are more reasons we can't get rid of `this`. If so, maybe we have arrived at a final state for problem (A): the lambda has to capture `this`, so be it. But if that's true, we still want a story for problem (B) as well (non-strictness of instance fields).
-------------
PR Comment: https://git.openjdk.org/jdk/pull/23972#issuecomment-2727157600
More information about the core-libs-dev
mailing list