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

Reference.isEnqueued() spec does not match the long-standing behavior returning true iff it's in the ref queue



    • Bug
    • Resolution: Fixed
    • P3
    • 16
    • None
    • core-libs
    • None
    • b28
    • generic
    • generic


      The documentation for Reference.isEnqueued() says

        public boolean isEnqueued()

        Tells whether or not this reference object has been enqueued, either
        by the program or by the garbage collector. If this reference object
        was not registered with a queue when it was created, then this
        method will always return false.

          true if and only if this reference object has been enqueued

      I read that as saying isEnqueued() is true iff the reference object has *ever* been enqueued, not whether it is *currently* in its associated queue. Specifically, once the reference object has been enqueued, I think isEnqueued() should always be true, with removal from the queue (by ReferenceQueue's poll() or remove() functions) not affecting the reference object's isEnqueued() state.

      However, the current implementation behaves differently, and appears to treat isEnqueued() as a test for whether the reference is currently in the associated queue.

      I think the cause of this behavior is that ReferenceQueue.reallyPoll() assigns r.queue = ReferenceQueue.NULL when removing a reference from the queue. This bit of code doesn't appear to have changed since the initial version in the hg repository. The associated implementation comment at the start of the Reference class definition similarly says, for the Enqueued state: "When an instance is removed from its ReferenceQueue, it is made Inactive." and the encoding for Inactive described later in the same comment has the queue field being NULL. That implementation comment has similarly been around since the initial hg version. I think that implementation comment correctly describes the current implementation, but that the current implementation is incorrect. I think the r.queue value when present in the queue will be ReferenceQueue.ENQUEUED, and it should be left with that value, rather than assigning it to ReferenceQueue.NULL. And of course the implementation comment needs to be updated.

      I noticed this because I was writing code that used ReferenceQueue.remove(long timeout) to wait and then testing a reference I was interested in to see if it was enqueued yet, rather than spin-waiting on isEnqueued(). That test unexpectedly never passed.

      I'm attaching a test program, TestIsEnqueued.java.


        Issue Links



              mchung Mandy Chung
              kbarrett Kim Barrett
              0 Vote for this issue
              7 Start watching this issue