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.