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
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
- relates to
-
JDK-6990442 (ref) Regression to clearing of a softly reachable object
- Open
-
JDK-6990438 (ref) Soft reference could consider strong if GC decides not to clear
- Open
-
JDK-6684579 SoftReference processing can be made more efficient
- Resolved