JDK-6220159 : (ref) JCK 15a tests WeakReference2003 and PhantomReference2010 failing
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 6
  • Priority: P2
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2005-01-21
  • Updated: 2010-04-02
  • Resolved: 2006-03-13
Related Reports
Duplicate :  
Description
Since switching to testing with JCK 1.5a, I've noticed new intermittently
failing test cases:

api/java_lang/ref/WeakReference/index.html#GCEnqueueing                                                                                                      Failed. test cases: 7; passed: 5; failed: 2; first test case failure: WeakReference2003

25264:api/java_lang/ref/PhantomReference/index.html#GCEnqueueing                                                                                                   Failed. test cases: 8; passed: 7; failed: 1; first test case failure: PhantomReference2010

Failures are always intermittent, occur on solaris-sparc, windows-amd64, and
linux-amd64.  The commonality appears to be that test failures only occur
on multiprocessor machines.

Here's a distilled standalone test for reproducing the WeakReference failure:

import java.lang.ref.*;
public class WeakReference2003 {
    static final long  WEAKREF_ENQUEUEING_TIMEOUT = 100000; 
    public static void main(String[] args) throws Throwable {
        try {
            ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
            WeakReference<Object> refWeak = new WeakReference<Object>(new Object(), queue);

            System.gc();
            long startTime = System.currentTimeMillis();
            while (System.currentTimeMillis() < (startTime + WEAKREF_ENQUEUEING_TIMEOUT)) {
                System.gc();
                if (refWeak.isEnqueued() == false) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException i) {
                    }
                    continue;
                }
                break;
            }
            if (refWeak.isEnqueued() == false) {
		throw new Exception(
		    WEAKREF_ENQUEUEING_TIMEOUT/1000 +
		    " seconds ellapsed since " +
		    "strong ref was removed, but WeakRef was not enqueued"); }
            if (refWeak.enqueue() == true) {
                throw new Exception("WeakRef(obj, queue): after GC enqueueing" +
				    " enqueue()==true");
            }
            return;

        } catch (Throwable e) {
            throw new Exception("Unexpected " + e + " was thrown");
        }
    }
}

This test fails for me about 50% of the time on my 2-cpu solaris-sparc machine.
###@###.### 2005-1-21 18:17:34 GMT

Comments
SUGGESTED FIX --- /u/martin/ws/mustang/src/share/classes/java/lang/ref/Reference.java 2004-08-27 15:53:58.618881000 -0700 +++ /u/martin/ws/queue/src/share/classes/java/lang/ref/Reference.java 2005-01-23 08:29:07.354124000 -0800 @@ -180,12 +180,8 @@ * @return <code>true</code> if and only if this reference object has * been enqueued */ - public boolean isEnqueued() { - /* In terms of the internal states, this predicate actually tests - whether the instance is either Pending or Enqueued */ - synchronized (this) { - return (this.queue != ReferenceQueue.NULL) && (this.next != null); - } + public synchronized boolean isEnqueued() { + return this.queue == ReferenceQueue.ENQUEUED; } /** ###@###.### 2005-1-24 21:26:02 GMT
24-01-2005

EVALUATION Reference.isEnqueued corresponds to the internal states Pending or Enqueued. However, the internal state "Pending" is an implementation detail and is not visible to the user. isEnqueued should have a meaning that is meaningful, and the obvious meaning is that the reference's queue contains this reference, so that q.poll will definitely return an object. ###@###.### 2005-1-24 21:26:02 GMT
21-01-2005