summaryrefslogtreecommitdiffstats
path: root/libart
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2014-09-18 18:31:52 -0700
committerMathieu Chartier <mathieuc@google.com>2014-09-19 14:07:21 -0700
commitfd8e1f6d0601cd025f7f9e4c605a396bbafe2a60 (patch)
treed1a848a53726ed019b3e0792d1593fc5ead5c1ad /libart
parent737ea55f0a003a07b90f88338da12b11b7d2859a (diff)
downloadlibcore-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.java33
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) {