11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2011 The Guava Authors 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License. 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License. 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.testing; 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static java.util.concurrent.TimeUnit.SECONDS; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.Beta; 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.ref.WeakReference; 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.CancellationException; 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.CountDownLatch; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ExecutionException; 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Future; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeoutException; 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Testing utilities relating to garbage collection finalization. 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Use this class to test code triggered by <em>finalization</em>, that is, one of the 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * following actions taken by the java garbage collection system: 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <ul> 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>invoking the {@code finalize} methods of unreachable objects 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>clearing weak references to unreachable referents 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>enqueuing weak references to unreachable referents in their reference queue 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * </ul> 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This class uses (possibly repeated) invocations of {@link java.lang.System#gc()} to cause 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * finalization to happen. However, a call to {@code System.gc()} is specified to be no more 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * than a hint, so this technique may fail at the whim of the JDK implementation, for example if 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * a user specified the JVM flag {@code -XX:+DisableExplicitGC}. But in practice, it works very 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * well for ordinary tests. 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Failure of the expected event to occur within an implementation-defined "reasonable" time 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * period or an interrupt while waiting for the expected event will result in a {@link 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * RuntimeException}. 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Here's an example that tests a {@code finalize} method: 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <pre> {@code 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * final CountDownLatch latch = new CountDownLatch(1); 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Object x = new MyClass() { 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * ... 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * protected void finalize() { latch.countDown(); ... } 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * }; 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * x = null; // Hint to the JIT that x is unreachable 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * GcFinalization.await(latch); 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * }</pre> 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Here's an example that uses a user-defined finalization predicate: 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <pre> {@code 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * final WeakHashMap<Object, Object> map = new WeakHashMap<Object, Object>(); 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * map.put(new Object(), Boolean.TRUE); 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * GcFinalization.awaitDone(new FinalizationPredicate() { 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * public boolean isDone() { 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * return map.isEmpty(); 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * } 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * }); 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * }</pre> 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This class cannot currently be used to test soft references, since this class does not try to 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * create the memory pressure required to cause soft references to be cleared. 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This class only provides testing utilities. It is not designed for direct use in production 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * or for benchmarking. 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author schmoe@google.com (mike nonemacher) 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author martinrb@google.com (Martin Buchholz) 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 11.0 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@Beta 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic final class GcFinalization { 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private GcFinalization() {} 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 10 seconds ought to be long enough for any object to be GC'ed and finalized. Unless we have a 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * gigantic heap, in which case we scale by heap size. 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static long timeoutSeconds() { 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // This class can make no hard guarantees. The methods in this class are inherently flaky, but 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // we try hard to make them robust in practice. We could additionally try to add in a system 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // load timeout multiplier. Or we could try to use a CPU time bound instead of wall clock time 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // bound. But these ideas are harder to implement. We do not try to detect or handle a 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // user-specified -XX:+DisableExplicitGC. 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // TODO(user): Consider using 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // java/lang/management/OperatingSystemMXBean.html#getSystemLoadAverage() 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // TODO(user): Consider scaling by number of mutator threads, 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // e.g. using Thread#activeCount() 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return Math.max(10L, Runtime.getRuntime().totalMemory() / (32L * 1024L * 1024L)); 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Waits until the given future {@linkplain Future#isDone is done}, invoking the garbage 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * collector as necessary to try to ensure that this will happen. 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws RuntimeException if timed out or interrupted while waiting 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public static void awaitDone(Future<?> future) { 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (future.isDone()) { 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final long timeoutSeconds = timeoutSeconds(); 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final long deadline = System.nanoTime() + SECONDS.toNanos(timeoutSeconds); 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert do { 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert System.runFinalization(); 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (future.isDone()) { 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert System.gc(); 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert future.get(1L, SECONDS); 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (CancellationException ok) { 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (ExecutionException ok) { 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (InterruptedException ie) { 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new RuntimeException("Unexpected interrupt while waiting for future", ie); 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (TimeoutException tryHarder) { 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /* OK */ 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } while (System.nanoTime() - deadline < 0); 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new RuntimeException( 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert String.format("Future not done within %d second timeout", timeoutSeconds)); 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Waits until the given latch has {@linkplain CountDownLatch#countDown counted down} to zero, 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * invoking the garbage collector as necessary to try to ensure that this will happen. 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws RuntimeException if timed out or interrupted while waiting 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public static void await(CountDownLatch latch) { 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (latch.getCount() == 0) { 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final long timeoutSeconds = timeoutSeconds(); 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final long deadline = System.nanoTime() + SECONDS.toNanos(timeoutSeconds); 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert do { 1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert System.runFinalization(); 1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (latch.getCount() == 0) { 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert System.gc(); 1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (latch.await(1L, SECONDS)) { 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (InterruptedException ie) { 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new RuntimeException("Unexpected interrupt while waiting for latch", ie); 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } while (System.nanoTime() - deadline < 0); 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new RuntimeException( 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert String.format("Latch failed to count down within %d second timeout", timeoutSeconds)); 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Creates a garbage object that counts down the latch in its finalizer. Sequestered into a 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * separate method to make it somewhat more likely to be unreachable. 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static void createUnreachableLatchFinalizer(final CountDownLatch latch) { 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new Object() { @Override protected void finalize() { latch.countDown(); }}; 1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * A predicate that is expected to return true subsequent to <em>finalization</em>, that is, one 1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * of the following actions taken by the garbage collector when performing a full collection in 1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * response to {@link System#gc()}: 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <ul> 1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>invoking the {@code finalize} methods of unreachable objects 1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>clearing weak references to unreachable referents 1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>enqueuing weak references to unreachable referents in their reference queue 1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * </ul> 1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public interface FinalizationPredicate { 1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean isDone(); 1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Waits until the given predicate returns true, invoking the garbage collector as necessary to 1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * try to ensure that this will happen. 2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws RuntimeException if timed out or interrupted while waiting 2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public static void awaitDone(FinalizationPredicate predicate) { 2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (predicate.isDone()) { 2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final long timeoutSeconds = timeoutSeconds(); 2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final long deadline = System.nanoTime() + SECONDS.toNanos(timeoutSeconds); 2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert do { 2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert System.runFinalization(); 2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (predicate.isDone()) { 2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert CountDownLatch done = new CountDownLatch(1); 2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert createUnreachableLatchFinalizer(done); 2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert await(done); 2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (predicate.isDone()) { 2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } while (System.nanoTime() - deadline < 0); 2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new RuntimeException( 2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert String.format("Predicate did not become true within %d second timeout", timeoutSeconds)); 2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Waits until the given weak reference is cleared, invoking the garbage collector as necessary 2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * to try to ensure that this will happen. 2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This is a convenience method, equivalent to: 2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <pre> {@code 2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * awaitDone(new FinalizationPredicate() { 2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * public boolean isDone() { 2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * return ref.get() == null; 2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * } 2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * }); 2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * }</pre> 2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws RuntimeException if timed out or interrupted while waiting 2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public static void awaitClear(final WeakReference<?> ref) { 2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert awaitDone(new FinalizationPredicate() { 2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public boolean isDone() { 2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return ref.get() == null; 2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }); 2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 248