Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6853696

(ref) ReferenceQueue.remove(timeout) may return null even if timeout has not expired

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 9
    • 6u14
    • core-libs
    • b04
    • x86
    • windows_xp
    • Verified

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

              igerasim Ivan Gerasimov
              ndcosta Nelson Dcosta (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: