[concurrency-interest] Is Reference.reachabilityFence() needed in Reference constructor?

Aleksey Shipilev aleksey.shipilev at oracle.com
Wed Oct 21 17:08:38 UTC 2015


On 10/21/2015 06:53 PM, Andrew Haley wrote:
> On 10/21/2015 04:44 PM, Aleksey Shipilev wrote:
>> Of course, this does not tell another (scary) part of the story, what if
>> the Reference itself is not discovered as strong ref by GC, e.g. when it
>> isn't published on heap, or scalarized by compiler, etc.
>> reachabilityFence, as currently implemented, extends the "liveness"
>> scope of the local variable, but does not convey anything special to the
>> GC/runtime otherwise.
> 
> If the Reference itself is not reachable from a strong root then the
> Reference is dead so we don't care what happens to it.  But if the
> Reference is put on a reachable ReferenceQueue, then it's fine.

Yes, if runtime stripes that instance before it is exposed anywhere
(e.g. scalarizes the weakref), or those references are dead (e.g. the
weakref is buried somewhere deep in garbage subgraph, and purged on
sweep), then everything goes awry.

But the thing is, a WeakReference is put on ReferenceQueue by the GC
itself. In the object graph, ReferenceQueue does not normally reference
weakrefs back. Before enqueueing the reference GC has to first discover
that WeakReference -- but from where? In other words, "registering" on a
reachable RefQueue does not make weakref to be reachable.

Case in point:

public class WhereIsWaldo {

    public static void main(String... args) throws Exception {
        for (int c = 0; true; c++) {
            new WhereIsWaldo().work(c);
        }
    }

    final ReferenceQueue<Object> rq = new ReferenceQueue<>();

    void work(int id) throws Exception {
        hideWaldo(id);
        findWaldo(id);
    }

    WeakReference<Object> gwr;

    void hideWaldo(int id) {
        // Does not work, d'uh
        new WeakReference<>(new Object(), rq);

        // Does not work either :(
        WeakReference<Object> wr =
           new WeakReference<>(new Object(), rq);

        // This also does not help... once you leave the method,
        // the weakref is gone.
        Reference.reachabilityFence(wr);

        // This one helps, makes Waldo reachable
        // gwr = wr;
    }

    void findWaldo(int id) throws Exception {
        while (Thread.currentThread().isAlive()) {
            System.gc();
            Reference ref = rq.remove(1000);
            if (ref != null) {
                return;
            } else {
                System.out.println("Where's Waldo #" + id + "?");
            }
        }
    }
}


Thanks,
-Aleksey




More information about the core-libs-dev mailing list