Commit fd8e1f6d authored by Mathieu Chartier's avatar Mathieu Chartier
Browse files

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 6ba68066)

Change-Id: Ide60db55190a3764c16e4919a7c71a113cbf3968
parent 737ea55f
......@@ -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) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment