----- Original Message ----- > From: "Dan Heidinga" <heidi...@redhat.com> > To: "Brian Goetz" <brian.go...@oracle.com> > Cc: "valhalla-spec-experts" <valhalla-spec-experts@openjdk.java.net> > Sent: Wednesday, February 9, 2022 5:50:29 PM > Subject: Re: SoV-2: weak references
> One option is to look at what we can do to help users prepare for IAE > when using value-based classes as keys to WHM. Can we take an > approach similar to JEP 390 [1] and provide JFR events that flag uses > of value-based classes as keys? It's not perfect but similar to JEP > 390, it does help users to know if they need to do something to > prepare for this. I wonder if there is not a difference between a weak reference of a value class and a weak reference on a primitive class. A weak reference on a primitive class makes no sense, a weak reference on a value class may make sense because a value class is handled by a pointer. > > --Dan Rémi > > [1] http://openjdk.java.net/jeps/390 > > On Thu, Jan 20, 2022 at 1:54 PM Dan Heidinga <heidi...@redhat.com> wrote: >> >> > >> > It certainly seems that all the choices are bad. >> > >> > The "obvious" choice is to simply say that WeakReference<Value> makes no >> > sense, >> > in that it sidesteps the hard semantics questions. >> >> It's an uncomfortable answer but it seems to provide the most >> defensible (and thus understandable) semantics for users. Values don't >> have an explicit lifetime and thus there is no way to tell when "this" >> copy of a value goes out of scope and can be collected. The object >> references (if any) held by the value are not a good proxy for its >> lifecycle - they can have either shorter or much longer life spans - >> and will make reasoning about when a WeakReference<Value> can be >> collected difficult for experts, let alone most users. >> >> > My fear is that this will cause new failures, where existing libraries >> > that toss >> > objects into WHMs to cache derived results, will start to experience new >> > failures when the value types show up in the heap (after all, >> > WeakReference::new takes Object.) >> >> This may be a case where the WeakReference constructor needs to be >> updated to take an IdentityObject and the old constructor marked as >> @Deprecated? Which doesn't solve the immediate problem but helps >> justify adding a "fail-fast" check to all WeakReference constructors >> so that they throw an IllegalArgumentException if the referent isn't >> an IdentityObject. >> >> This won't avoid failures but it does make it very clear what went >> wrong rather than introducing "strange", hard to diagnose failures. >> >> > And we'll have to have something to tell those users, because they >> > declared a >> > WeakHashMap<User, UserData>, and someone created a value subtype of User -- >> > which seems entirely valid. >> > >> > It is possible we could do something special with WHM, since it is layered >> > atop >> > WR, but that still begs the question -- what? >> >> Starting from the conclusion that WeakReference<Value> is a >> meaningless entity, what are the options here? >> >> 1) Make it impossible to use a Value as a key in a WeakHashMap. >> ::put(key, value) & ::pulAll(Map m) will throw if a key is a Value >> object. ::containsKey(Object) will always be false if the Object is a >> ValueObject. This makes WeakHashMap unusable with Values. The >> semantics are clear but all existing uses of WeakHashMap will need to >> be adapted to defensively check for Values and do something (tbd) to >> avoid the exceptions. >> >> 2) Use strong references for Value keys in WeakHashMap. >> Treat each Value object used as a key in WeakHashMap as a strong >> reference. This means Value keys will never be removed and will keep >> their corresponding map value alive forever (or until explicitly >> removed). While this will allow WeakHashMaps to continue to be used >> as Maps for Values, it will break the contract for WHM and may >> introduce memory leaks into otherwise correct programs. >> >> 3) Pick some other object to act as the reference when using a Value >> key in a WHM. >> This is basically the solution we rejected for WeakReference<Value> >> and all the same problems apply here. It may allow existing code to >> "keep working" when it first deals with Values but introduces strange >> failure cases and difficult to reason about rules. It avoids >> exceptions but leaves the code doing the wrong thing with no way to >> tell. >> >> Anyone see another option here? >> > > --Dan