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

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

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P4
    • Resolution: Fixed
    • Affects Version/s: 6u14
    • Fix Version/s: 9
    • Component/s: core-libs
    • Labels:
    • Subcomponent:
    • Resolved In Build:
      b04
    • CPU:
      x86
    • OS:
      windows_xp
    • Verification:
      Verified

      Backports

        Description

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

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  igerasim Ivan Gerasimov
                  Reporter:
                  ndcosta Nelson Dcosta
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  1 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved:
                    Imported:
                    Indexed: