JDK-4214755 : (ref) JDK1.2 handling of nested refs seems to go against API spec
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.2.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: solaris_2.6
  • CPU: generic
  • Submitted: 1999-02-24
  • Updated: 2010-10-07
  • Resolved: 2010-10-07
Related Reports
Relates :  
Relates :  
Relates :  
Description
Consider the following test program:

import java.lang.ref.*;
import java.util.*;

public class RefCompliance {
    
    RefCompliance () {
    }

    public static void test() {

        int[] o1 = new int[10];

        WeakReference w1 = new WeakReference(o1);
        SoftReference s1 = new SoftReference(w1);

        int[] o2 = new int[10];

        WeakReference w2 = new WeakReference(o2);
        SoftReference s2 = new SoftReference(w2);

        int[] o3 = new int[10];

        WeakReference w3 = new WeakReference(o3);

        o1 = null;
        o2 = null;
        o3 = null;
        w2 = null;

        // Scrub stack because of conservative collector
        int[] dummy1 = new int[10];
        int[] dummy2 = new int[10];

        System.gc();

        int res1;

        w2 = (WeakReference)s2.get();
        if (w1 == s1.get()) {
            res1 = 0;
            if (w1.get() == null) {
                res1 += 100;
            }
            if (w2.get() == null) {
                res1 += 10;
            }
            if (w3.get() == null) {
                res1 += 1;
            }
        } else {
            res1 = -1;
        }

        if (res1 == 101) {
            System.err.println("JDK1.2");
        } else if (res1 == 111) {
            System.err.println("weakest link on strongest chain");
        } else if (res1 == 001) {
            System.err.println("API spec");
        } else {
            System.err.println("unknown: result " + res1);
        }
    }

    public static void main(String[] args) {
        test();
        test();
        test();
        test();
        test();
    }
}


When run with JDK1.2 it outputs "JDK1.2".  According to my understanding
of the API spec, it should instead output "API spec".  Because the
JDK uses a conservative collector, it is also possible that no refs
will be cleared and the test will output "API spec" for JDK1.2.  This
is because a stale reference to the referent might be found on the C or
Java stack, preventing the ref from being cleared.  For this reason the
test is run multiple times.  My tests show the full output as:

API spec
JDK1.2
JDK1.2
JDK1.2
JDK1.2

for JDK1.2, and

weakest link on strongest chain
weakest link on strongest chain
weakest link on strongest chain
weakest link on strongest chain
weakest link on strongest chain

for a modified VM that attempts to implement the "intuitive" behavior.
My guess is that the Solaris "Exact" VM would print "JDK1.2" each time.

dean.long@Eng 1999-02-24

Comments
EVALUATION This (i.e., "JDK1.2") is the expected behavior. None of the soft references will be cleared since the program hasn't come anywhere near the capacity of the heap. Considering each case in turn: - w1.get() should return null because w1 is strongly reachable from the local variable w1 itself, but o1 is not reachable at all. - w2.get() should not return null because o2 is reachable only via s2, i.e., it is softly reachable. w2.get() will return null some time after s2 has been cleared, at which point o2 becomes weakly reachable. - w3.get() should return null because w3 is strongly reachable, but o3 is not reachable at all. Hence the correct result is 101, and this is not a bug.
11-06-2004