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.

--Dan

[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

Reply via email to