RFR 9: 8138696 : java.lang.ref.Cleaner - an easy to use alternative to finalization

Peter Levart peter.levart at gmail.com
Tue Nov 3 13:58:22 UTC 2015


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.
>




More information about the core-libs-dev mailing list