In the Dec 2021 update to State of Valhalla, part 2: The language model, the section on "Identity-sensitive operations" states this about weak references:
> Weak references to value objects that contain no references to identity > objects should never be > cleared; weak references to value objects that contain references to identity > objects should be > cleared when those objects are no longer strongly reachable. I'm concerned that this approach makes using weak references correctly for values very difficult, especially in the face of scalarization. Scalarization allows separating values into their individual components and flowing them separately through the code. This can - with some caveats for decompilation and maybe other features - result in very different lifetimes for each separate component, with some object references going out of scope "earlier" than expected. The source code will of course show the *entire* value being carried along even though only a single component may survive post-scalarization which means developers will see very different behaviour between the interpreter (which doesn't scalarize) and jitted code - making it very easy to write tests that give them the wrong impression. Reference::reachabilityFence was added in Java 9 to help users deal with premature finalization and has gotten little attention from most users. The proposed semantics for WeakReferences on value objects will drag the reachabilityFence method into the light and expose users to a problem they'd rather not have. Just as we avoided exposing most users to tearing of their (bucket 2) value objects, we shouldn't expose them to having to reason about complicated reachability rules. Which is to say, Reference objects and value objects need to be incompatible to give users what they expect. Anything else is loading a gun and pointing it at their feet. Here's an example of why the suggested rules for weak references using the identity objects may bring reachability issues to the forefront (where we don't want them): public value class ResourcePair { static long nativePtr; static IdentityObject companion; ResourcePair(long ptr, IdentityObject o) { nativePtr = ptr; companion = o; } } class PtrRef extends WeakReference<ResourcePair> { long nativePtr; PtrRef(ResourcePair p, ReferenceQueue q) { super(p, q); nativePtr = p.nativePtr; } void free() { /* do something to nativePtr */ } } If the `companion` object of the ResourcePair value goes out of scope before `nativePtr` is done being used - the issue of reachabilityFence - the ReferenceQueue processor could call free() before the `nativePtr` is done being used. Scalarization will make this more common and even very common if we're getting the benefits we expect from it. --Dan