diff options
author | Mathieu Chartier <mathieuc@google.com> | 2014-09-18 18:31:52 -0700 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2014-09-19 14:07:21 -0700 |
commit | fd8e1f6d0601cd025f7f9e4c605a396bbafe2a60 (patch) | |
tree | d1a848a53726ed019b3e0792d1593fc5ead5c1ad /libart | |
parent | 737ea55f0a003a07b90f88338da12b11b7d2859a (diff) | |
download | libcore-fd8e1f6d0601cd025f7f9e4c605a396bbafe2a60.zip libcore-fd8e1f6d0601cd025f7f9e4c605a396bbafe2a60.tar.gz libcore-fd8e1f6d0601cd025f7f9e4c605a396bbafe2a60.tar.bz2 |
Change FinalizerWatchdogDaemon to not hold objects live
Previously, waitForFinalization would hold whatever object was being
finalized live for MAX_FINALIZE_NANOS even though the finalizer on
this object was run much earlier. This caused a test to be flaky since
it was assuming that the JNI weak global reference of a recently
finalized object wouldn't be held live.
Bug: 17305633
(cherry picked from commit 6ba680664fa14a547543a8c63708543ea8072680)
Change-Id: Ide60db55190a3764c16e4919a7c71a113cbf3968
Diffstat (limited to 'libart')
-rw-r--r-- | libart/src/main/java/java/lang/Daemons.java | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/libart/src/main/java/java/lang/Daemons.java b/libart/src/main/java/java/lang/Daemons.java index 1422c13..71a8d86 100644 --- a/libart/src/main/java/java/lang/Daemons.java +++ b/libart/src/main/java/java/lang/Daemons.java @@ -192,6 +192,7 @@ public final class Daemons { // The RI silently swallows these, but Android has always logged. System.logE("Uncaught exception thrown by finalizer", ex); } finally { + // Done finalizing, stop holding the object as live. finalizingObject = null; } } @@ -207,24 +208,29 @@ public final class Daemons { @Override public void run() { while (isRunning()) { - Object object = waitForObject(); - if (object == null) { + boolean waitSuccessful = waitForObject(); + if (waitSuccessful == false) { // We have been interrupted, need to see if this daemon has been stopped. continue; } - boolean finalized = waitForFinalization(object); + boolean finalized = waitForFinalization(); if (!finalized && !VMRuntime.getRuntime().isDebuggerActive()) { - finalizerTimedOut(object); - break; + Object finalizedObject = FinalizerDaemon.INSTANCE.finalizingObject; + // At this point we probably timed out, look at the object in case the finalize + // just finished. + if (finalizedObject != null) { + finalizerTimedOut(finalizedObject); + break; + } } } } - private Object waitForObject() { + private boolean waitForObject() { while (true) { Object object = FinalizerDaemon.INSTANCE.finalizingObject; if (object != null) { - return object; + return true; } synchronized (this) { // wait until something is ready to be finalized @@ -233,7 +239,7 @@ public final class Daemons { wait(); } catch (InterruptedException e) { // Daemon.stop may have interrupted us. - return null; + return false; } } } @@ -257,9 +263,14 @@ public final class Daemons { } } - private boolean waitForFinalization(Object object) { - sleepFor(FinalizerDaemon.INSTANCE.finalizingStartedNanos, MAX_FINALIZE_NANOS); - return object != FinalizerDaemon.INSTANCE.finalizingObject; + private boolean waitForFinalization() { + long startTime = FinalizerDaemon.INSTANCE.finalizingStartedNanos; + sleepFor(startTime, MAX_FINALIZE_NANOS); + // If we are finalizing an object and the start time is the same, it must be that we + // timed out finalizing something. It may not be the same object that we started out + // with but this doesn't matter. + return FinalizerDaemon.INSTANCE.finalizingObject == null || + FinalizerDaemon.INSTANCE.finalizingStartedNanos != startTime; } private static void finalizerTimedOut(Object object) { |