Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
FULL PRODUCT VERSION : java version "1.6.0_10" Java(TM) SE Runtime Environment (build 1.6.0_10-b33) Java HotSpot(TM) Client VM (build 11.0-b15, mixed mode, sharing) java version "1.7.0-ea-fastdebug" Java(TM) SE Runtime Environment (build 1.7.0-ea-fastdebug-b58) Java HotSpot(TM) Client VM (build 16.0-b02-fastdebug, mixed mode) A DESCRIPTION OF THE PROBLEM : ReferenceQueue.remove(timeout) may return null even if given timeout period has not expired. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - ReferenceQueue.remove(timeout) should wait until either next reference object in this queue becomes available or the given timeout period expires, but not earlier or far later. ACTUAL - Exception in thread "main" java.lang.Error: timeout: 5000; actual time: 1000 at Main.main(Main.java:38) REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; public class Main extends Thread { static ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); static Object referent = new Object(); static WeakReference<Object> reference = new WeakReference<Object>(referent, queue); long timeout; long actual; boolean suspect; Main(long timeout) { this.timeout = timeout; } public static void main(String... args) throws Exception { final int LONG_TIMEOUT = 5000; final int SHORT_WAIT_TIME = 1000; final int TOLERANCE = 1000; assert LONG_TIMEOUT > SHORT_WAIT_TIME : "Bad initial parameters"; assert LONG_TIMEOUT - SHORT_WAIT_TIME > TOLERANCE : "Bad initial parameters"; Main[] threads = new Main[2]; for (int i = 0, n = threads.length; i < n; ++i) { threads[i] = new Main(LONG_TIMEOUT); threads[i].start(); } Thread.sleep(SHORT_WAIT_TIME); referent = null; System.gc(); for (Main thread : threads) { thread.join(); } for (Main thread : threads) { if (thread.suspect && Math.abs(thread.timeout - thread.actual) > TOLERANCE) { throw new Error("timeout: " + thread.timeout + "; actual time: " + thread.actual); } } } public void run() { try { long start = System.currentTimeMillis(); Reference<?> reference = queue.remove(timeout); actual = System.currentTimeMillis() - start; suspect = reference == null; } catch (InterruptedException exc) { exc.printStackTrace(); } } } ---------- END SOURCE ----------