Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.testing;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.common.annotations.Beta;
import java.lang.ref.WeakReference;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
/**
* Testing utilities relating to garbage collection finalization.
*
*
Use this class to test code triggered by finalization, that is, one of the
* following actions taken by the java garbage collection system:
*
*
*
invoking the {@code finalize} methods of unreachable objects
*
clearing weak references to unreachable referents
*
enqueuing weak references to unreachable referents in their reference queue
*
*
*
This class uses (possibly repeated) invocations of {@link java.lang.System#gc()} to cause
* finalization to happen. However, a call to {@code System.gc()} is specified to be no more
* than a hint, so this technique may fail at the whim of the JDK implementation, for example if
* a user specified the JVM flag {@code -XX:+DisableExplicitGC}. But in practice, it works very
* well for ordinary tests.
*
*
Failure of the expected event to occur within an implementation-defined "reasonable" time
* period or an interrupt while waiting for the expected event will result in a {@link
* RuntimeException}.
*
*
Here's an example that tests a {@code finalize} method:
*
*
{@code
* final CountDownLatch latch = new CountDownLatch(1);
* Object x = new MyClass() {
* ...
* protected void finalize() { latch.countDown(); ... }
* };
* x = null; // Hint to the JIT that x is stack-unreachable
* GcFinalization.await(latch);}
*
*
Here's an example that uses a user-defined finalization predicate:
*
*
{@code
* final WeakHashMap
*
*
Even if your non-test code does not use finalization, you can
* use this class to test for leaks, by ensuring that objects are no
* longer strongly referenced:
*
*
{@code
* // Helper function keeps victim stack-unreachable.
* private WeakReference fooWeakRef() {
* Foo x = ....;
* WeakReference weakRef = new WeakReference(x);
* // ... use x ...
* x = null; // Hint to the JIT that x is stack-unreachable
* return weakRef;
* }
* public void testFooLeak() {
* GcFinalization.awaitClear(fooWeakRef());
* }}
*
*
This class cannot currently be used to test soft references, since this class does not try to
* create the memory pressure required to cause soft references to be cleared.
*
*
This class only provides testing utilities. It is not designed for direct use in production
* or for benchmarking.
*
* @author mike nonemacher
* @author Martin Buchholz
* @since 11.0
*/
@Beta
public final class GcFinalization {
private GcFinalization() {}
/**
* 10 seconds ought to be long enough for any object to be GC'ed and finalized. Unless we have a
* gigantic heap, in which case we scale by heap size.
*/
private static long timeoutSeconds() {
// This class can make no hard guarantees. The methods in this class are inherently flaky, but
// we try hard to make them robust in practice. We could additionally try to add in a system
// load timeout multiplier. Or we could try to use a CPU time bound instead of wall clock time
// bound. But these ideas are harder to implement. We do not try to detect or handle a
// user-specified -XX:+DisableExplicitGC.
//
// TODO(user): Consider using
// java/lang/management/OperatingSystemMXBean.html#getSystemLoadAverage()
//
// TODO(user): Consider scaling by number of mutator threads,
// e.g. using Thread#activeCount()
return Math.max(10L, Runtime.getRuntime().totalMemory() / (32L * 1024L * 1024L));
}
/**
* Waits until the given future {@linkplain Future#isDone is done}, invoking the garbage
* collector as necessary to try to ensure that this will happen.
*
* @throws RuntimeException if timed out or interrupted while waiting
*/
public static void awaitDone(Future> future) {
if (future.isDone()) {
return;
}
final long timeoutSeconds = timeoutSeconds();
final long deadline = System.nanoTime() + SECONDS.toNanos(timeoutSeconds);
do {
System.runFinalization();
if (future.isDone()) {
return;
}
System.gc();
try {
future.get(1L, SECONDS);
return;
} catch (CancellationException ok) {
return;
} catch (ExecutionException ok) {
return;
} catch (InterruptedException ie) {
throw new RuntimeException("Unexpected interrupt while waiting for future", ie);
} catch (TimeoutException tryHarder) {
/* OK */
}
} while (System.nanoTime() - deadline < 0);
throw new RuntimeException(
String.format("Future not done within %d second timeout", timeoutSeconds));
}
/**
* Waits until the given latch has {@linkplain CountDownLatch#countDown counted down} to zero,
* invoking the garbage collector as necessary to try to ensure that this will happen.
*
* @throws RuntimeException if timed out or interrupted while waiting
*/
public static void await(CountDownLatch latch) {
if (latch.getCount() == 0) {
return;
}
final long timeoutSeconds = timeoutSeconds();
final long deadline = System.nanoTime() + SECONDS.toNanos(timeoutSeconds);
do {
System.runFinalization();
if (latch.getCount() == 0) {
return;
}
System.gc();
try {
if (latch.await(1L, SECONDS)) {
return;
}
} catch (InterruptedException ie) {
throw new RuntimeException("Unexpected interrupt while waiting for latch", ie);
}
} while (System.nanoTime() - deadline < 0);
throw new RuntimeException(
String.format("Latch failed to count down within %d second timeout", timeoutSeconds));
}
/**
* Creates a garbage object that counts down the latch in its finalizer. Sequestered into a
* separate method to make it somewhat more likely to be unreachable.
*/
private static void createUnreachableLatchFinalizer(final CountDownLatch latch) {
new Object() { @Override protected void finalize() { latch.countDown(); }};
}
/**
* A predicate that is expected to return true subsequent to finalization, that is, one
* of the following actions taken by the garbage collector when performing a full collection in
* response to {@link System#gc()}:
*
*
*
invoking the {@code finalize} methods of unreachable objects
*
clearing weak references to unreachable referents
*
enqueuing weak references to unreachable referents in their reference queue
*
*/
public interface FinalizationPredicate {
boolean isDone();
}
/**
* Waits until the given predicate returns true, invoking the garbage collector as necessary to
* try to ensure that this will happen.
*
* @throws RuntimeException if timed out or interrupted while waiting
*/
public static void awaitDone(FinalizationPredicate predicate) {
if (predicate.isDone()) {
return;
}
final long timeoutSeconds = timeoutSeconds();
final long deadline = System.nanoTime() + SECONDS.toNanos(timeoutSeconds);
do {
System.runFinalization();
if (predicate.isDone()) {
return;
}
CountDownLatch done = new CountDownLatch(1);
createUnreachableLatchFinalizer(done);
await(done);
if (predicate.isDone()) {
return;
}
} while (System.nanoTime() - deadline < 0);
throw new RuntimeException(
String.format("Predicate did not become true within %d second timeout", timeoutSeconds));
}
/**
* Waits until the given weak reference is cleared, invoking the garbage collector as necessary
* to try to ensure that this will happen.
*
*
*
* @throws RuntimeException if timed out or interrupted while waiting
*/
public static void awaitClear(final WeakReference> ref) {
awaitDone(new FinalizationPredicate() {
public boolean isDone() {
return ref.get() == null;
}
});
}
/**
* Tries to perform a "full" garbage collection cycle (including processing of weak references
* and invocation of finalize methods) and waits for it to complete. Ensures that at least one
* weak reference has been cleared and one {@code finalize} method has been run before this
* method returns. This method may be useful when testing the garbage collection mechanism
* itself, or inhibiting a spontaneous GC initiation in subsequent code.
*
*
In contrast, a plain call to {@link java.lang.System#gc()} does not ensure finalization
* processing and may run concurrently, for example, if the JVM flag {@code
* -XX:+ExplicitGCInvokesConcurrent} is used.
*
*
Whenever possible, it is preferable to test directly for some observable change resulting
* from GC, as with {@link #awaitClear}. Because there are no guarantees for the order of GC
* finalization processing, there may still be some unfinished work for the GC to do after this
* method returns.
*
*
This method does not create any memory pressure as would be required to cause soft
* references to be processed.
*
* @throws RuntimeException if timed out or interrupted while waiting
* @since 12.0
*/
public static void awaitFullGc() {
final CountDownLatch finalizerRan = new CountDownLatch(1);
WeakReference ref = new WeakReference(
new Object() {
@Override protected void finalize() { finalizerRan.countDown(); }
});
await(finalizerRan);
awaitClear(ref);
// Hope to catch some stragglers queued up behind our finalizable object
System.runFinalization();
}
}