diff options
author | Mathieu Chartier <mathieuc@google.com> | 2015-06-04 18:38:24 -0700 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2015-06-05 15:06:56 -0700 |
commit | 51855ccb72d01a28babedbaed70974d4f3697ab0 (patch) | |
tree | b57ae5327fe974441d53c674d687d60e514ed1c4 | |
parent | 438f476f72a90637b085db2bf8a9209ef6e903fe (diff) | |
download | libcore-51855ccb72d01a28babedbaed70974d4f3697ab0.zip libcore-51855ccb72d01a28babedbaed70974d4f3697ab0.tar.gz libcore-51855ccb72d01a28babedbaed70974d4f3697ab0.tar.bz2 |
Add VMRuntime.runFinalizationWithTimeout
Used by native allocations to prevent deadlocks.
Bug: 21544853
Change-Id: I57b2f7ae8b74185922eb3c15ba0ab71a4d2348aa
-rw-r--r-- | libart/src/main/java/dalvik/system/VMRuntime.java | 25 | ||||
-rw-r--r-- | luni/src/main/java/java/lang/Runtime.java | 12 | ||||
-rw-r--r-- | luni/src/main/java/java/lang/ref/FinalizerReference.java | 21 |
3 files changed, 47 insertions, 11 deletions
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java index b885ed2..aa3f154 100644 --- a/libart/src/main/java/dalvik/system/VMRuntime.java +++ b/libart/src/main/java/dalvik/system/VMRuntime.java @@ -16,6 +16,7 @@ package dalvik.system; +import java.lang.ref.FinalizerReference; import java.util.HashMap; import java.util.Map; @@ -301,6 +302,30 @@ public final class VMRuntime { */ public native void registerNativeFree(int bytes); + /** + * Wait for objects to be finalized. + * + * If finalization takes longer than timeout, then the function returns before all objects are + * finalized. + * + * @param timeout + * timeout in nanoseconds of the maximum time to wait until all pending finalizers + * are run. If timeout is 0, then there is no timeout. Note that the timeout does + * not stop the finalization process, it merely stops the wait. + * + * @see #Runtime.runFinalization() + * @see #wait(long,int) + */ + public static void runFinalization(long timeout) { + try { + FinalizerReference.finalizeAllEnqueued(timeout); + } catch (InterruptedException e) { + // Interrupt the current thread without actually throwing the InterruptionException + // for the caller. + Thread.currentThread().interrupt(); + } + } + public native void requestConcurrentGC(); public native void concurrentGC(); public native void requestHeapTrim(); diff --git a/luni/src/main/java/java/lang/Runtime.java b/luni/src/main/java/java/lang/Runtime.java index 3ddacf7..ad549f2 100644 --- a/luni/src/main/java/java/lang/Runtime.java +++ b/luni/src/main/java/java/lang/Runtime.java @@ -34,6 +34,7 @@ package java.lang; import dalvik.system.BaseDexClassLoader; import dalvik.system.VMDebug; +import dalvik.system.VMRuntime; import dalvik.system.VMStack; import java.io.File; import java.io.IOException; @@ -438,20 +439,17 @@ public class Runtime { String ldLibraryPath, String dexPath); /** - * Provides a hint to the VM that it would be useful to attempt + * Provides a hint to the runtime that it would be useful to attempt * to perform any outstanding object finalization. */ public void runFinalization() { - try { - FinalizerReference.finalizeAllEnqueued(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } + // 0 for no timeout. + VMRuntime.runFinalization(0); } /** * Sets the flag that indicates whether all objects are finalized when the - * VM is about to exit. Note that all finalization which occurs + * runtime is about to exit. Note that all finalization which occurs * when the system is exiting is performed after all running threads have * been terminated. * diff --git a/luni/src/main/java/java/lang/ref/FinalizerReference.java b/luni/src/main/java/java/lang/ref/FinalizerReference.java index 5416a80..02cfa01 100644 --- a/luni/src/main/java/java/lang/ref/FinalizerReference.java +++ b/luni/src/main/java/java/lang/ref/FinalizerReference.java @@ -82,7 +82,7 @@ public final class FinalizerReference<T> extends Reference<T> { /** * Waits for all currently-enqueued references to be finalized. */ - public static void finalizeAllEnqueued() throws InterruptedException { + public static void finalizeAllEnqueued(long timeout) throws InterruptedException { // Alloate a new sentinel, this creates a FinalizerReference. Sentinel sentinel; // Keep looping until we safely enqueue our sentinel FinalizerReference. @@ -91,7 +91,7 @@ public final class FinalizerReference<T> extends Reference<T> { do { sentinel = new Sentinel(); } while (!enqueueSentinelReference(sentinel)); - sentinel.awaitFinalization(); + sentinel.awaitFinalization(timeout); } private static boolean enqueueSentinelReference(Sentinel sentinel) { @@ -144,9 +144,22 @@ public final class FinalizerReference<T> extends Reference<T> { notifyAll(); } - synchronized void awaitFinalization() throws InterruptedException { + synchronized void awaitFinalization(long timeout) throws InterruptedException { + final long startTime = System.nanoTime(); + final long endTime = startTime + timeout; while (!finalized) { - wait(); + // 0 signifies no timeout. + if (timeout != 0) { + final long currentTime = System.nanoTime(); + if (currentTime >= endTime) { + break; + } else { + final long deltaTime = endTime - currentTime; + wait(deltaTime / 1000000, (int)(deltaTime % 1000000)); + } + } else { + wait(); + } } } } |