8141596: java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java starts failing intermittently

Reviewed-by: martin, psandoz, dholmes
This commit is contained in:
Doug Lea 2017-03-03 10:45:38 -08:00
parent 1506580766
commit 908c3c315e

View File

@ -34,12 +34,12 @@
/* /*
* @test * @test
* @summary Ensure that waiting pool threads don't retain refs to tasks. * @summary Ensure that waiting pool threads don't retain refs to tasks.
* @library /lib/testlibrary/
*/ */
import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Delayed; import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -47,10 +47,8 @@ import java.util.concurrent.RunnableScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import jdk.testlibrary.Utils;
public class GCRetention { public class GCRetention {
static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
/** /**
* A custom thread pool with a custom RunnableScheduledFuture, for the * A custom thread pool with a custom RunnableScheduledFuture, for the
@ -80,53 +78,48 @@ public class GCRetention {
} }
} }
int countRefsCleared(WeakReference<?>[] refs) { void removeAll(ReferenceQueue<?> q, int n) throws InterruptedException {
int count = 0; for (int j = n; j--> 0; ) {
for (WeakReference<?> ref : refs) if (q.poll() == null) {
if (ref.get() == null) for (;;) {
count++; System.gc();
return count; if (q.remove(1000) != null)
break;
System.out.printf(
"%d/%d unqueued references remaining%n", j, n);
}
}
}
check(q.poll() == null);
} }
void test(String[] args) throws Throwable { void test(String[] args) throws Throwable {
CustomPool pool = new CustomPool(10); final CustomPool pool = new CustomPool(10);
final int size = 100; final int size = 100;
WeakReference<?>[] refs = new WeakReference<?>[size]; final ReferenceQueue<Object> q = new ReferenceQueue<>();
Future<?>[] futures = new Future<?>[size]; final List<WeakReference<?>> refs = new ArrayList<>(size);
for (int i = 0; i < size; i++) { final List<Future<?>> futures = new ArrayList<>(size);
final Object x = new Object();
refs[i] = new WeakReference<Object>(x); // Schedule custom tasks with strong references.
// Create a Runnable with a strong ref to x. class Task implements Runnable {
Runnable r = new Runnable() { final Object x;
public void run() { System.out.println(x); } Task() { refs.add(new WeakReference<>(x = new Object(), q)); }
}; public void run() { System.out.println(x); }
// Schedule a custom task with a strong reference to r.
// Later tasks have earlier expiration, to ensure multiple
// residents of queue head.
futures[i] = pool.schedule(r, size*2-i, TimeUnit.MINUTES);
}
Thread.sleep(10);
for (int i = 0; i < size; i++) {
if (futures[i] != null) {
futures[i].cancel(false);
futures[i] = null;
}
} }
// Give tasks added later earlier expiration, to ensure
// multiple residents of queue head.
for (int i = size; i--> 0; )
futures.add(pool.schedule(new Task(), i + 1, TimeUnit.MINUTES));
futures.forEach(future -> future.cancel(false));
futures.clear();
pool.purge(); pool.purge();
int cleared = 0; removeAll(q, size);
for (int i = 0; for (WeakReference<?> ref : refs) check(ref.get() == null);
i < 10 && (cleared = countRefsCleared(refs)) < size;
i++) {
System.gc();
System.runFinalization();
Thread.sleep(10);
}
pool.shutdown(); pool.shutdown();
pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS); // rely on test harness to handle timeout
if (cleared < size) pool.awaitTermination(1L, TimeUnit.DAYS);
throw new Error(String.format
("references to %d/%d tasks retained (\"leaked\")",
size - cleared, size));
} }
//--------------------- Infrastructure --------------------------- //--------------------- Infrastructure ---------------------------