RFR: 8132306: java/lang/ref/ReferenceEnqueue.java fails with "RuntimeException: Error: poll() returned null; expected ref object"

Peter Levart peter.levart at gmail.com
Thu Jul 30 11:57:03 UTC 2015



On 07/30/2015 01:44 PM, David Holmes wrote:
>> r.isEnqueued() && q.poll() == null && r.isEnqueued() ==> true
>>
>>
>> What is surprising in the above expression evaluating to true is the
>> fact that 'r' appears to be enqueued before and after the q.poll()
>> returns null. I can easily imagine code that would fail because it never
>> imagined above expression to evaluate to true. For example:
>
> So r has been enqueued and one poll() removes it, so the second poll() 
> returns NULL, but r still claims to be enqueued. Sorry I'm not seeing 
> how that is possible.
>
> David 

'r' has been enqueued.

Thread-1:

r.isEnqueued() &&
q.poll() == null &&
r.isEnqueued()

Thread-2:

q.poll();


Sequence of actions:

T1: r.isEnqueued() ==> true

T2: q.poll() executed to the following point (see HERE) and 'r' was the 
last element in the queue ('head' has been assigned to null):

     public Reference<? extends T> poll() {
         if (head == null)
             return null;
         synchronized (lock) {
             return reallyPoll();
         }
     }

     private Reference<? extends T> reallyPoll() {       /* Must hold 
lock */
         Reference<? extends T> r = head;
         if (r != null) {
             head = (r.next == r) ?
                 null :
                 r.next; // Unchecked due to the next field having a raw 
type in Reference

             // >> HERE <<<

             r.queue = NULL;
             r.next = r;
             queueLength--;
             if (r instanceof FinalReference) {
                 sun.misc.VM.addFinalRefCount(-1);
             }
             return r;
         }
         return null;
     }

T1: q.poll() finds head == null and returns null;

T1: r.isEnqueued() ==> true since r.queue is still ENQUEUED


Regards, Peter



More information about the hotspot-gc-dev mailing list