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

(ref) Reference.enqueue is not thread safe

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P3 P3
    • 8
    • 6u10
    • core-libs

      FULL PRODUCT VERSION :
      java version "1.6.0_01"
      Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
      Java HotSpot(TM) Server VM (build 1.6.0_01-b06, mixed mode)

      Problem also exists in JDK6 Mercurial repository http://hg.openjdk.java.net/jdk6/jdk6/jdk/summary as of changeset 135 a42d6999734b

      ADDITIONAL OS VERSION INFORMATION :
      Linux 2.6.24-gg23-generic #1 SMP Fri Jan 30 14:07:49 PST 2009 x86_64 GNU/Linux


      A DESCRIPTION OF THE PROBLEM :
      It is possible for a Reference.enqueue() call to return true twice on the same Reference instance.

      The issue appears to be that ReferenceQueue.enqueue(Reference) does not check for

        if (r.queue == NULL) return false;

      Consequently what can happen is:

       - some thread T1 enqueues the reference via Reference.enqueue().

       - T1 calls ReferenceQueue.poll() and takes the monitor on the ReferenceQueue.

       - T1 removes the Reference, setting Reference.queue = NULL.

       - T1 gets preempted by the scheduler before it can release the monitor on the ReferenceQueue.

       - some thread T2 starts to call Reference.enqueue(), acquires the monitor on the Reference

       - T2 skips passes through the existing "if (r.queue == ENQUEUED) return false;" test

       - T2 blocks on the monitor on the ReferenceQueue (it is held by T1).

       - scheduler resumes T1, which releases the monitor on the ReferenceQueue.

       - scheduler resumes T2, which takes the monitor on the ReferenceQueue and puts the same Reference back into the queue.

       - T2 sees Reference.enqueue() return true for the same Reference that T1 saw it return true on.

       - A future ReferenceQueue.poll() will dequeue the same Reference again.

      If the application is using the ReferenceQueue to implement reference counting based resource management, a double dequeue of the same reference is unexpected. The Javadoc for Reference.enqueue() seems to imply that a single Reference instance will enqueue/dequeue exactly once from its registered ReferenceQueue, but as the scenario above outlines, that isn't true.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I expected to see each Reference instance enqueue/dequeue exactly once from the registered ReferenceQueue. Instead a Reference can enqueue/dequeue an infinite number of times.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      CUSTOMER SUBMITTED WORKAROUND :
      Maintain a cleared flag in your Reference subclass, e.g.:

      public class MyRef<V> extends SoftReference<V> {
        private boolean cleared;

        public MyRef(V v, ReferenceQueue<V> q) {
          super(v, q);
        }

        public boolean canClear() {
          if (cleared) return false;
          cleared = true;
          return true;
        }
      }

      MyRef<V> r;
      while ((r = (MyRef<V>) queue.poll()) != null) {
        if (!r.canClear()) continue;
        // normally handle the reference as this is the one (and only) dequeue
      }

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

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: