JDK-8016643 : ReferenceQueue.remove(timeout) may wait too long
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 7
  • Priority: P3
  • Status: Resolved
  • Resolution: Not an Issue
  • Submitted: 2013-03-20
  • Updated: 2014-02-23
  • Resolved: 2014-02-20
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :


A DESCRIPTION OF THE PROBLEM :
http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/4436a3e97a9b/src/share/classes/java/lang/ref/ReferenceQueue.java

In the following code, timeout is not decreased after the wait() call, so if the for loop executes more than one time, the total time waited may be significantly greater than the timeout specified.

      131         synchronized (lock) {
      132             Reference<? extends T> r = reallyPoll();
      133             if (r != null) return r;
      134             for (;;) {
      135                 lock.wait(timeout);
      136                 r = reallyPoll();
      137                 if (r != null) return r;
      138                 if (timeout != 0) return null;
      139             }
      140         }


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Set up a ReferenceQueue. Add a thread that slowly creates objects that will be enqueued in it. Call remove(timeout) from many threads.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No individual call to remove will take significantly longer than the timeout specified, up to the system-provides resolution of the wait() call.
ACTUAL -
When remove(timeout) callers race to respond to the notifyAll(), and there are too few items in the ReferenceQueue to satisfy all of them, the loop will result in some callers waiting longer than specified.

REPRODUCIBILITY :
This bug can be reproduced always.

CUSTOMER SUBMITTED WORKAROUND :
Ensure that for any given ReferenceQueue, at most one thread is calling any version of remove() or poll() at any given time.
Comments
On the other hand, if lock.wait(timeout); hasn't waited long enough, the function may return too early. This problem will be covered in JDK-6853696.
23-02-2014

In the code: 138 if (timeout != 0) return null; Therefore, the loop will be executed more than once only if timeout == 0. No need to decrement it after wait().
20-02-2014