summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2018-02-09 23:02:01 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2018-02-09 23:02:01 +0000
commit9c05f652921a411bd46a0172802c5d3bf14cff93 (patch)
tree05d33e8a4d90bae20d6fc99598bdafb1b3b04ace
parent0ea7d2a56479480169c6b646062ca985f6e60e51 (diff)
parente2a06b0c95582ff8c4a6029aadfdd1560b547461 (diff)
downloadapache-harmony-9c05f652921a411bd46a0172802c5d3bf14cff93.tar.gz
Merge "Refine GcMarker to wait for finalization."
-rw-r--r--jdwp/src/test/java/org/apache/harmony/jpda/tests/share/GcMarker.java58
1 files changed, 47 insertions, 11 deletions
diff --git a/jdwp/src/test/java/org/apache/harmony/jpda/tests/share/GcMarker.java b/jdwp/src/test/java/org/apache/harmony/jpda/tests/share/GcMarker.java
index c41066c..28e3d88 100644
--- a/jdwp/src/test/java/org/apache/harmony/jpda/tests/share/GcMarker.java
+++ b/jdwp/src/test/java/org/apache/harmony/jpda/tests/share/GcMarker.java
@@ -18,21 +18,41 @@
package org.apache.harmony.jpda.tests.share;
-import java.lang.ref.WeakReference;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
/**
- * A class that allows one to observe GCs.
+ * A class that allows one to observe GCs and finalization.
*/
public class GcMarker {
- private Object marker;
- private WeakReference<Object> markerRef;
+
+ private static int mCount = 0;
+
+ /**
+ * Sentinel object with explicit finalizer
+ * to avoid optimizations around empty finalizer.
+ */
+ private static class Sentinel {
+ Sentinel() { mCount++; }
+ protected void finalize() { mCount--; }
+ }
+
+ private final ReferenceQueue mQueue;
+
+ private Sentinel marker;
+ private PhantomReference<Sentinel> markerRef;
public GcMarker() {
+ mQueue = new ReferenceQueue();
reset();
}
private boolean isLive() {
- return markerRef.get() != null;
+ // Pedantically check mCount as well once the phantom reference
+ // link is enqueued to make sure we have really finalized (since
+ // there is only a single finalizer thread, this means all other
+ // finalizers are finished too).
+ return !markerRef.isEnqueued() || mCount > 0;
}
private void allowCollection() {
@@ -40,19 +60,35 @@ public class GcMarker {
}
private void reset() {
- marker = new Object();
- markerRef = new WeakReference<Object>(marker);
+ marker = new Sentinel();
+ markerRef = new PhantomReference<Sentinel>(marker, mQueue);
}
public void waitForGc() {
+ // Start with a full collection to discourage minor collections in the middle of this.
+ // Minor collections could cause us to collect the Sentinel but not older objects.
+ Runtime.getRuntime().gc();
+
+ // Release the sentinel.
allowCollection();
- // Requests GC and finalization of objects.
+
+ // Another collection.
+ Runtime.getRuntime().gc();
+
+ // Request finalization of objects, and subsequent reference enqueueing.
do {
- try { Thread.sleep(10); } catch (Exception e) {}
- System.gc();
System.runFinalization();
- System.gc();
+ Runtime.getRuntime().gc();
+ try { Thread.sleep(10); } catch (Exception e) {}
} while (isLive());
+
+ // Remove the phantom reference from the queue and reset the only
+ // remaining reference to the phantom reference to break the
+ // sentinel's "phantom reachability".
+ try { mQueue.remove(); } catch (Exception e) {}
+ markerRef = null;
+
+ // Prepare for the next waitForGc().
reset();
}
}