/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ import java.lang.ref.SoftReference; import org.jikesrvm.VM; import org.vmmagic.pragma.Uninterruptible; /** * A test case for RVM-1067 (Overly eager clearing of soft references). * <p> * Description of the test case based on the mail that reported the bug: * <pre> * When a soft reference A is reachable only though another soft * reference B, the garbage collector failed to preserve the correct * semantics before the bug from this test case was fixed. * * In this test case, there are 3 objects. A "normal" object is directly * reachable from a local variable, o. * A SoftReference object is also directly reachable from a local * variable, rr. Its referent, call it r, is another SoftReference object, * which in turn has as its referent, o. Immediately prior to GC, * r is soft reachable from rr (and only from rr). Thus, using the * notation -s-> to indicate a soft reference, and naming objects * by the variables that point to them, immediately before GC we * have: * root ---> rr -s-> r -s-> o <--- root * * The specification for soft references permits two actions on a * softly reachable (and by definition, not strongly reachable) object: * it preserves the object or it may choose to reclaim it. The only softly * reachable object in this scenario is r. * * In the former case, the object graph above is unchanged. Specifically, * r == rr.get() && r.get() == o. * In the latter case, after GC, rr.get() == null. * However, r.get() returned null on Jikes RVM before the bug fix, * which should be impossible * since either r == rr.get() == null and we should get an NPE when we call r.get(), * or r == rr.get() != null and r.get() should return o. * </pre> */ public class SoftReferenceClearingTest { public static void main(String[] args) throws Exception { Object o = new Object(); SoftReference<Object> r = new SoftReference<Object>(o); SoftReference<SoftReference<Object>> rr = new SoftReference<SoftReference<Object>>(r); r = null; System.gc(); r = rr.get(); boolean success = determineTestSuccess(o, r); if (success) { System.out.println("ALL TESTS PASSED"); } else { System.out.println("SOME TESTS FAILED"); } } @Uninterruptible public static boolean determineTestSuccess(Object o, SoftReference<Object> r) { boolean testSuccess = false; VM.sysWriteln("o is null: "); VM.sysWriteln(o == null); VM.sysWriteln("r is null: "); VM.sysWriteln(r == null); if (r != null) { VM.sysWriteln("r.get() is null: "); Object referentOfR = java.lang.ref.JikesRVMSupport.uninterruptibleReferenceGet(r); VM.sysWriteln(referentOfR == null); if (referentOfR != null && referentOfR == o) { testSuccess = true; } else { testSuccess = false; } } else { testSuccess = true; } return testSuccess; } }