diff options
author | Aart Bik <ajcbik@google.com> | 2018-02-09 23:18:07 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2018-02-09 23:18:07 +0000 |
commit | 9b7e41e1c89180fc8955b7daf233b5e73bf89d4a (patch) | |
tree | 05d33e8a4d90bae20d6fc99598bdafb1b3b04ace | |
parent | fb40f85d6da8c8bf43320a8b1c2f30745621d8f5 (diff) | |
parent | 9c05f652921a411bd46a0172802c5d3bf14cff93 (diff) | |
download | apache-harmony-9b7e41e1c89180fc8955b7daf233b5e73bf89d4a.tar.gz |
Merge "Refine GcMarker to wait for finalization."
am: 9c05f65292
Change-Id: If0f50c2fd98a3210c97dda690f751e370a2df0ad
-rw-r--r-- | jdwp/src/test/java/org/apache/harmony/jpda/tests/share/GcMarker.java | 58 |
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(); } } |