This is the mail archive of the mauve-patches@sources.redhat.com mailing list for the Mauve project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Weak/phantom test "fixes"


The tests for weak and phantom references can generate false negatives
because the specified VM behavior is loose. In practice one way these
tests "fail" is because conservative GC stack scans find dead references
on the stack, i.e., references which are no longer going to be used.

This patch allocates the referent objects in a separate thread, then
lets that thread exit, to avoid this particular problem. This "fixes"
these tests for at least JC and possibly other VMs.

Let me know if anyone sees any problems with this patch.

Thanks,
-Archie

__________________________________________________________________________
Archie Cobbs      *        CTO, Awarix        *      http://www.awarix.com
Index: gnu/testlet/java/lang/ref/PhantomReference/phantom.java
===================================================================
RCS file: /cvs/mauve/mauve/gnu/testlet/java/lang/ref/PhantomReference/phantom.java,v
retrieving revision 1.4
diff -u -r1.4 phantom.java
--- gnu/testlet/java/lang/ref/PhantomReference/phantom.java	3 Dec 2004 08:00:25 -0000	1.4
+++ gnu/testlet/java/lang/ref/PhantomReference/phantom.java	30 Dec 2004 20:35:11 -0000
@@ -34,6 +34,7 @@
 public class phantom implements Testlet
 {
   public static int final_count = 0;
+  public static phantom nogc;
 
   public phantom ()
   {
@@ -44,37 +45,58 @@
     ++final_count;
   }
 
-  public PhantomReference genRef (ReferenceQueue q, Object o)
+  static class Reffer extends Thread
   {
-    return new PhantomReference (o, q);
+    ReferenceQueue q;
+    TestHarness harness;
+    PhantomReference wr;
+    phantom twt;
+
+    public Reffer (ReferenceQueue q, TestHarness harness)
+    {
+      this.q = q;
+      this.harness = harness;
+    }
+
+    public void run()
+    {
+      twt = new phantom ();
+      wr = new PhantomReference (twt, q);
+
+      // Give the runtime some hints that it should really garbage collect.
+      System.gc ();
+      System.runFinalization();
+      System.gc ();
+      System.runFinalization();
+
+      Reference r = q.poll ();
+      harness.check (r, null, "live reference");
+      harness.check (final_count, 0);
+    }
   }
 
-  public PhantomReference try1 (ReferenceQueue q, TestHarness harness)
+  public void test (TestHarness harness)
   {
-    phantom twt = new phantom ();
-    PhantomReference wr = genRef (q, twt);
-
-    // Give the runtime some hints that it should really garbage collect.
-    System.gc ();
-    System.runFinalization();
-    System.gc ();
-    System.runFinalization();
-
-    Reference r = q.poll ();
-    harness.check (r, null, "live reference");
-    harness.check (final_count, 0);
 
-    // Must keep the phantom object live.
-    System.out.println(twt);
+    // Make sure 'this' is not finalized while running the test.
+    nogc = this;
 
-    return wr;
-  }
-
-  public void test (TestHarness harness)
-  {
     ReferenceQueue q = new ReferenceQueue ();
 
-    PhantomReference wr = try1 (q, harness);
+    // Create reference in a separate thread so no inadvertent references
+    // to the contained object are left on the stack, which causes VM's that
+    // do conservative stack GC scans to report false negatives for this test.
+    Reffer reffer = new Reffer(q, harness); 
+    reffer.start();
+    try {
+      reffer.join();
+    } catch (InterruptedException e) {
+      throw new RuntimeException(e);
+    }
+    PhantomReference wr = reffer.wr;
+
+    // Phantom reference "should" get cleared here
+    reffer.twt = null;
     System.gc ();
     System.runFinalization();
     System.gc ();
@@ -92,8 +114,5 @@
 
     harness.check (r, wr, "unreachable");
     harness.check (final_count, 1, "object finalized");
-
-    // Make sure we're not GCed while running the test.
-    System.out.println(this);
   }
 }
Index: gnu/testlet/java/lang/ref/WeakReference/weakref.java
===================================================================
RCS file: /cvs/mauve/mauve/gnu/testlet/java/lang/ref/WeakReference/weakref.java,v
retrieving revision 1.1
diff -u -r1.1 weakref.java
--- gnu/testlet/java/lang/ref/WeakReference/weakref.java	27 Sep 2001 15:44:09 -0000	1.1
+++ gnu/testlet/java/lang/ref/WeakReference/weakref.java	30 Dec 2004 20:35:11 -0000
@@ -33,31 +33,51 @@
 
 public class weakref implements Testlet
 {
-  public WeakReference genRef (ReferenceQueue q, Object o)
-  {
-    return new WeakReference (o, q);
-  }
 
-  public WeakReference try1 (ReferenceQueue q, TestHarness harness)
+  static class Reffer extends Thread
   {
-    Integer twt = new Integer (23);
-    WeakReference wr = genRef (q, twt);
-
-    System.gc ();
-
-    Reference r = q.poll ();
-    harness.check (r, null, "live reference");
-    harness.check (wr.get (), twt);
-
-    // Must keep the WeakReference live.
-    return wr;
+    ReferenceQueue q;
+    TestHarness harness;
+    WeakReference wr;
+    Integer twt;
+
+    public Reffer (ReferenceQueue q, TestHarness harness)
+    {
+      this.q = q;
+      this.harness = harness;
+    }
+
+    public void run()
+    {
+      twt = new Integer (23);
+      wr = new WeakReference (twt, q);
+
+      System.gc ();
+
+      Reference r = q.poll ();
+      harness.check (r, null, "live reference");
+      harness.check (wr.get (), twt);
+    }
   }
 
   public void test (TestHarness harness)
   {
     ReferenceQueue q = new ReferenceQueue ();
 
-    WeakReference wr = try1 (q, harness);
+    // Create reference in a separate thread so no inadvertent references
+    // to the contained object are left on the stack, which causes VM's that
+    // do conservative stack GC scans to report false negatives for this test.
+    Reffer reffer = new Reffer(q, harness); 
+    reffer.start();
+    try {
+      reffer.join();
+    } catch (InterruptedException e) {
+      throw new RuntimeException(e);
+    }
+    WeakReference wr = reffer.wr;
+
+    // Weak reference "should" get cleared here
+    reffer.twt = null;
     System.gc ();
 
     Reference r = null;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]