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

Alex Otenko oleksandr.otenko at gmail.com
Mon Oct 26 17:12:35 UTC 2015


Wouldn’t it be possible to add a test that will always be false?

eg

   Reference(T referent, ReferenceQueue<? super T> queue) {
        this.referent = referent;
        // - safepoint with GC happens, 'referent' is found weakly-reachable, 'this' Reference is hooked on the pending chain
        // - ReferenceHandler thread unhooks 'this' from pending chain and tries to enqueue it, but this.queue is still null
        // - BANG! NPE in Referencehandler thread which terminates it!
        this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
        if (get() != referent) { // do a get() == referent test instead for Phantom ref
    System.out.println(referent + “ expected but “ + get() + “ found");
  }
    } 

The point being that referent would need to stay alive due to Java semantics to align with get() and queue assignment.

Alex

> On 21 Oct 2015, at 10:08, Aleksey Shipilev <aleksey.shipilev at oracle.com> wrote:
> 
> 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
> 
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest




More information about the core-libs-dev mailing list