Hi,

Here's a demonstration that shows the "reachability" race:

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;

/**
 * A demonstration of WeakReference initialization race
 */
public class WeakRace extends WeakReference<Object> {

    static volatile boolean pause;

    int value;

    public WeakRace(Object referent, ReferenceQueue<? super Object> q) {
        super(referent, q);
        init();
    }

    private void init() {
        if (pause) try {
            Thread.sleep(500L);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        value = 123;
    }

    static void monitor(ReferenceQueue<Object> queue) {
        while (true) try {
            WeakRace wr = (WeakRace) queue.remove();
            int value = wr.value;
            if (value == 0) {
                System.out.println("Got value: " + value);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    static void constructor(ReferenceQueue<Object> queue) {
        WeakRace[] wrs = new WeakRace[10000];
        while (true) {
            for (int i = 0; i < wrs.length; i++) {
                wrs[i] = new WeakRace(new Object(), queue);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        ReferenceQueue<Object> queue = new ReferenceQueue<>();

        new Thread(() -> monitor(queue), "Monitor").start();
        new Thread(() -> constructor(queue), "Constructor").start();

        for (int i = 0; i < 30; i++) {
            Thread.sleep(1000L);
            WeakRace.pause = true;
            Thread.sleep(1L);
            System.gc();
            WeakRace.pause = false;
        }
    }
}


Running this program nicely outputs:

Got value: 0
Got value: 0
Got value: 0
Got value: 0
Got value: 0
Got value: 0
...

once per second.

Adding referent.getClass() call after init() in WeakRace constructor "fixes" it, but I would rather use reachabilityFence() for that purpose to be more reliable.


Regards, Peter


On 10/21/2015 04:52 PM, Roger Riggs wrote:
Hi Andrew,

So then is is correct to conclude that the gc does examine fields in instances
still being constructed to determine reachability?

How is that we have gone so long without needing reachabilityFence?
Or is it just because optimizers have taken so long to get a perfect view of reference scope?

Thanks, Roger


On 10/21/2015 10:45 AM, Andrew Haley wrote:
On 10/21/2015 02:58 PM, Daniel Fuchs wrote:
I do hope that method parameters are not eagerly gc'ed before
the method returns
They are -- that's what reachabilityFence() is for.  I don't think
that constructors have any special rules, and nor should they.

Andrew.


Reply via email to