WeakReference, reachabilityFence, and Java Memory Model

Viewed 405

Suppose ref is a WeakReference object pointing to (or at a certain moment having pointed to) an object obj. If a call ref.get() happens-before (or at least precedes in the program order?) an execution of Reference.reachabilityFence(obj), is there any chance that the returnee of the ref.get() may be null? (in addition, I want to ask this question again after replacing the part about the observation of null through ref.get() by the acquisition of the ref through queue polling.)

I ask this question because I am not quite sure how Reference#reachabilityFence works in terms of Java Memory Model, especially when it interacts with WeakReferences (and other similar references). The following list is all the places where specifications related to this topic exist, as far as I know:

The problem is that the terminology used in (c) and (d) is vague and unclear compared to the one used in (a) and (b).

If the answer to the question written at the beginning is sadly yes, how can I make all the ref.get() calls happening-before a certain point of code? If not, how can we prove that based on the specifications written in (a)(b)(c)(d) or anywhere else?

Although the answer to the first question may be enough for my use, I also want the specifications in (c) and in (d) to become clear, so let me ask more questions below.

First, (c)WeakReference says that at a certain point of time the gc determines objects to be weakly-reachable, at the same time clears weak refs, and at the same time declares those objects as finalizable. According to (b2), reachability checks and finalizability declarations take place at reachability decision points. So the "certain point of time" must be one of the reachability decision points, right ? If so, other questions come up. (b2) also says reachability desicion points are NOT actual points (unlike writes and reads) in the code or on the program order; they are virtual points that are only related to actions through come-before / come-after relations, which are independent of program ordering. So... weak refs are cleared at the decision point, which is not anywhere on the code. What does it exactly mean ? On what condition can WeakReference#get() be null? cannot be null? Is it the come-before / come-after relation between the decision point and the WeakReference#get() that we need? Or the come-before / after relation between the decision point and some other action which has a certain memory-model-related relation to the WeakReference#get()?

Next, (d)reachabilityFence. It says a call of this method keeps the object's strong reachability and thus makes it unreclaimable until after the call. Can I interpret it as saying that the call keeps the object's strong reachability until after the call ? Technically it is not saying so. But if there is no specification about until when the strong reachability are kept, the part about keeping the strong reachability is useless. (And the other half talking about the undefined concept "unreclaimability" is useless from the beginning.) So the strong reachability is maintained until after the call -- but what does the word 'after' exactly mean ? Program order? Happens before? The order in which comissions take place? Besides, I think objects become unreachable at a certain decision point as described in (b2). What determines whether a certain call of reachabilityFence affects a certain decision point or it does not? The come-before / come-after relation between the fence and the decision point? Obviously not, because since the call of fence is neither a write nor a read nor a synchronization action, it makes no difference whether a certain fence call comes-before or comes-after a certain decision point.

I suspect (c) and (d) are too vague and thus it is impossible to answer basic questions like my first one.

1 Answers

To answer your first question : No. And that is exactly what the documentation says:

Ensures that the object referenced by the given reference remains strongly reachable, regardless of any prior actions of the program that might otherwise cause the object to become unreachable; thus, the referenced object is not reclaimable by garbage collection at least until after the invocation of this method

So calling Reference.reachabilityFence(obj) establishes a strong reference to obj. It does not matter what that obj was wrapped in a WeakReference (so that "...might otherwise cause the object to become unreachable..."), it will stay strongly reachable.

I am not exactly sure what you are looking for with at a certain point of time, but may be this will help. A GC cycle might scan (and as such discover weak references) only partial regions of the heap. It can scan only some regions (in case of regionalized collectors like G1) and thus simply skip the regions where your weak reference might be located. That means the discovery and clearing of weak references is non-deterministic. Some GC algorithms even have scheduled collection of these special references : that is even if they discover it now, they might skip clearing it for next X cycles. You can effectively delay clearing such a reference on purpose (ShenandoahRefProcFrequency). It will happen, but unknown when, neither in what GC cycle.

That is probably what reachability decision points is. This decision is made at the point when a GC encounters such a special reference.

I am also not exactly sure where confusion comes from with the word after. Since the call of Reference.reachabilityFence(obj); should normally happen only in a method, that to me is program order, which according to the JLS is also happens-before relationship.

Related