Phantom Referencesvs finalizers (was: RFR JDK-8185582, Update Zip implementation to use Cleaner, not finalizers)
kim.barrett at oracle.com
Wed Sep 27 21:12:37 UTC 2017
> On Sep 27, 2017, at 1:55 PM, Hans Boehm <hboehm at google.com> wrote:
> "And of course, it guarantees that the tracked referent can not be
> resurrected as a result of cleanup code execution."
> True, but it seems to me that the real property you want is "it guarantees
> that the tracked referent can not be resurrected". Full stop. Actually, the
> property I really need is: "The referent of an enqueued PhantomReference
> cannot subsequently be accessed."
> Unfortunately, neither of those last two appear to be true due to the
> weakly specified behavior of JNI WeakGlobalRefs. The spec says:
> "Interactions between weak global references and PhantomReferences are
> undefined. In particular, implementations of a Java VM may (or may not)
> process weak global references after PhantomReferences, and it may (or may
> not) be possible to use weak global references to hold on to objects which
> are also referred to by PhantomReference objects. This undefined use of
> weak global references should be avoided."
> This allows a WeakGlobalRef to be converted to a strong JNI ref after a
> PhantomReference to the same object has been enqueued, thus resurrecting
> the referent, and allowing access.
> The advice in the last sentence seems to be both essential and completely
> impractical, since the WeakGlobalRef may point to another object, which may
> then indirectly point ot the PhantomReference referent. Hence you can't
> prevent this interaction without global, whole program knowledge of which
> objects may indirectly reference PhantomReference referents. This is
> essentially the same problem we had with (unordered) finalization, only now
> confined to programs that use WeakGlobalRefs.
> Am I reading this correctly? Is it intended? It seems like it should be
> fixable by giving WeakGlobalRefs essentially WeakReference behavior, as the
> name implies?
That quote from the JNI specification is, I think, left over from
before JDK-8071507. Now that PhantomReferences are cleared when their
referent is no longer referenced, the effective strength of phantoms
and JNI weak references are equivalent, at least in Hotspot.
The java.lang.ref and JNI specifications seem to allow the possibility
that an implementation will clear references at a given strength
without clearing references of a weaker strength, even if that would
allow the referent of one of those stronger references to be obtained
via one of those weaker references. (And indeed, that must be possible
for finalize.) I'm not sure that's intentional though (except for
finalize), and I've seen discussions  suggesting that it would be
at least surprising to behave that way; Hotspot certainly doesn't, and
those discussions suggested that neither do any of the other
implementations. This suggests some specification tightening is called
for, in order to address these concerns around post-Cleaner cleanup
Giving WeakGlobalRefs essentially WeakReference behavior has been
tried in the past, and doing so broke some code.  Whether that's
still relevant is probably moot now, because of JDK-8071507.
More information about the core-libs-dev