The java.lang.ref.Reference class constructor presently sets the referent, then the queue. However, if a GC occurs between those assignments and the GC determines the referent is dead, the GC will add the partially constructed reference to the pending list. If the reference processing thread then runs before the constructor assigns the queue field, it will encounter a reference with a null (not ReferenceQueue.NULL) queue and get an unhandled NPE. And having the reference processing thread be more circumspect in its handling of the queue isn't sufficient, since then the notification will be lost.
A similar problem exists if a GC discovers the referent of a soft reference is not strongly reachable before the reference's timestamp field is set. In this case the consequences are probably less severe than an exception; the reference will probably just be deemed a candidate for clearing because it appears to not have been accessed for a long time.
It seems like this sort of thing could arise with any reference class, where the reference might be enqueued and become accessible to a thread monitoring the queue before the reference is fully constructed.
A similar issue came up with the recently added java.lang.ref.Cleaner, where the referent needs to be kept alive until the reference has been recorded. So it isn't even just "fully constructed" that can be a problem. In that case the proposed solution was to use the new Reference.reachabilityFence to ensure the needed minimum lifetime of the referent.
I don't know of a general automatic solution to this issue; perhaps documentation describing the issue and referring to reachabilityFence?
A similar problem exists if a GC discovers the referent of a soft reference is not strongly reachable before the reference's timestamp field is set. In this case the consequences are probably less severe than an exception; the reference will probably just be deemed a candidate for clearing because it appears to not have been accessed for a long time.
It seems like this sort of thing could arise with any reference class, where the reference might be enqueued and become accessible to a thread monitoring the queue before the reference is fully constructed.
A similar issue came up with the recently added java.lang.ref.Cleaner, where the referent needs to be kept alive until the reference has been recorded. So it isn't even just "fully constructed" that can be a problem. In that case the proposed solution was to use the new Reference.reachabilityFence to ensure the needed minimum lifetime of the referent.
I don't know of a general automatic solution to this issue; perhaps documentation describing the issue and referring to reachabilityFence?
- relates to
-
JDK-8177915 Clarify Reference.reachabilityFence use
- Open
-
JDK-8286742 Ensure Cleaner.Cleanable instance is not reclaimed until cleaning is complete
- Open
-
JDK-8291867 Cleaner has reachabilityFence in wrong place
- Open
-
JDK-8169605 reachabilityFence needs to be optimized away by the JIT
- Closed