Here's another finalization-related issue, this time hopefully appropriate for this list. This was inspired by looking at the Ugawa, Jones, and Ritson paper from ISMM 2014, which I belatedly had a chance to look at.
The java.lang.ref spec says: "An object is phantom reachable if it is neither strongly, softly, nor weakly reachable, it has been finalized, and some phantom reference refers to it." It notably does not say that such an object must not be reachable from unfinalized objects. I currently believe that: 1) This spec is not as intended, in that it allows a PhantomReference to X to be enqueued while X is still actively being used. My understanding is that PhantomReferences were invented largely to make that impossible. 2) Real production implementations enforce a stronger requirement, which includes that the PhantomReference must not reachable from unfinalized objects with a nontrivial finalizer, which prevents this problem. 3) The ISMM 2014 paper may have been confused by this, in that it seems to mirror the official spec rather than the usual implementation. It (surprisingly to me) does not appear to address the fact that implementations generally mark reachable objects in at least two stages: (1) Reachability from roots, and (2) Reachability from roots U unfinalized finalizable objects, where the result of the first phase is used to determine WeakReference clearing, while the result of the second phase determines PhantomReference clearing, and what to collect. Am I correct? A scenario that I believe can fail according to the spec, but cannot and must not fail in real life, is the following, where F1 and F2 are objects with nontrivial finalizers, and P is the referent of a PhantomReference: Consider F1 --> P, where P has a PhantomReference referring to it, and <root> -> F2 -> null. Then 1) F1's finalizer runs and notionally P's (empty) finalizer runs. F1 modifies F2, so it gets a strong reference to P. [ P has now been finalized. We have <root> -> F2 -> P ] 2) <root> is cleared, making F2 unreachable. [ P is not strongly, softly or weakly referenced, and has been finalized. Therefore P is phantom reachable. ] 3) The PhantomReference to P is enqueued, resulting in running a Cleaner that e.g. deallocates native memory required by P. 4) F2's finalizer runs and accesses P. 5) Bad stuff. Although this is arguably a weird corner case that is unlikely to occur frequently, I think it profoundly changes the algorithms used to implement this. "Has been finalized" is not the correct check; it's reachability from a not-yet-finalized object that matters. Hence the implementation must do a reachability analysis not technically required by the current spec. [ Just saying that in the spec probably doesn't work either. I suspect the fact that the finalizer is nontrivial also matters to get reasonable progress guarantees. Currently I think the spec doesn't have that notion, but it seems annoyingly essential. ] Clearly, this problem goes away if you get rid of finalizers and merge {Phantom,Weak}References, which is presumably the intended end state, but not one that looks imminent to me. Hans