blob: c7768fd57647c5b1257791b4467d872e4498ef52 (
plain) (
tree)
|
|
package test;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.RunListener;
import org.junit.Assert;
import java.lang.ref.WeakReference;
public class ContextEscapeDetector extends RunListener {
//context can be captured by objects, eg NoDenotation
public static final int CONTEXTS_ALLOWED = 1;
@Override
public void testRunFinished(Result result) throws Exception {
if (contextsAlive() > CONTEXTS_ALLOWED) {
forceGCHeuristic0();
if (contextsAlive() > CONTEXTS_ALLOWED) {
forceGCHeuristic1();
if (contextsAlive() > CONTEXTS_ALLOWED) {
forceGCHeuristic2();
forceGCHeuristic1();
int contextAlive = contextsAlive();
if (contextAlive > CONTEXTS_ALLOWED) {
StringBuilder names = new StringBuilder();
for (ContextEscapeDetection.TestContext ref : ContextEscapeDetection.contexts) {
if (ref.context.get() != null) names.append(ref.testName).append(' ');
}
Assert.fail("Multiple contexts survived test suite: " + names.toString());
}
}
}
}
super.testRunFinished(result);
}
private static synchronized int contextsAlive() {
int count = 0;
for (ContextEscapeDetection.TestContext ref : ContextEscapeDetection.contexts) {
if (ref.context.get() != null) count++;
}
return count;
}
private static volatile Object o = null;
private static synchronized void forceGCHeuristic0() {
System.gc();
Runtime.getRuntime().gc();
System.gc();
Runtime.getRuntime().gc();
System.gc();
Runtime.getRuntime().gc();
System.gc();
Runtime.getRuntime().gc();
System.gc();
}
private static synchronized void forceGCHeuristic1() {
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
obj = null;
while (ref.get() != null) {
System.gc();
}
}
private static synchronized void forceGCHeuristic2() {
try {
Object[] arr = new Object[1024]; // upto 8 GB
WeakReference ref = new WeakReference<Object>(arr);
o = arr; // make sure array isn't optimized away
Runtime runtime = Runtime.getRuntime();
// allocate memory until no more that 64MB is left
for (int i = 0; i < 1024 &&
runtime.totalMemory() != runtime.maxMemory() ||
runtime.freeMemory() < 1024 * 1024 * 64; i++) {
int[] data = new int[1024 * 1024]; // 8MB
for (int j = 0; j < 1024 * 1024; j++) {
data[j] = j; // force actual pages allocation
}
arr[i] = data;
}
o = null;
arr = new Object[128];
o = arr;
// allocate 1 more GB
for (int i = 0; i < 128; i++) {
int[] data = new int[1024 * 1024]; // 8MB
for (int j = 0; j < 1024 * 1024; j++) {
data[j] = j; // force actual pages allocation
}
arr[i] = data;
}
o = null;
arr = null;
forceGCHeuristic0();
while (ref.get() != null) {
System.gc();
}
} catch (OutOfMemoryError e) {
o = null;
// just swallow
}
}
}
|