提交 d4eb1192 编写于 作者: M mchung

6992968:...

6992968: test/java/lang/management/MemoryMXBean/CollectionUsageThresholdConcMarkSweepGC.sh should not hang
Reviewed-by: alanb, dholmes
上级 b62906ac
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 4959889 * @bug 4959889 6992968
* @summary Basic unit test of memory management testing: * @summary Basic unit test of memory management testing:
* 1) setCollectionUsageThreshold() and getCollectionUsageThreshold() * 1) setCollectionUsageThreshold() and getCollectionUsageThreshold()
* 2) test notification emitted for two different memory pools. * 2) test notification emitted for two different memory pools.
...@@ -34,8 +34,10 @@ ...@@ -34,8 +34,10 @@
* @run main/timeout=300 CollectionUsageThreshold * @run main/timeout=300 CollectionUsageThreshold
*/ */
import java.lang.Thread.*;
import java.lang.management.*; import java.lang.management.*;
import java.util.*; import java.util.*;
import java.util.concurrent.*;
import javax.management.*; import javax.management.*;
import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeData;
...@@ -52,6 +54,12 @@ public class CollectionUsageThreshold { ...@@ -52,6 +54,12 @@ public class CollectionUsageThreshold {
private static Checker checker; private static Checker checker;
private static int numGCs = 0; private static int numGCs = 0;
// semaphore to signal the arrival of a low memory notification
private static Semaphore signals = new Semaphore(0);
// barrier for the main thread to wait until the checker thread
// finishes checking the low memory notification result
private static CyclicBarrier barrier = new CyclicBarrier(2);
static class PoolRecord { static class PoolRecord {
private MemoryPoolMXBean pool; private MemoryPoolMXBean pool;
private int listenerInvoked = 0; private int listenerInvoked = 0;
...@@ -98,10 +106,9 @@ public class CollectionUsageThreshold { ...@@ -98,10 +106,9 @@ public class CollectionUsageThreshold {
} }
pr.addNotification(minfo); pr.addNotification(minfo);
synchronized (this) { synchronized (this) {
System.out.println("notifying the checker thread to check result");
numNotifs++; numNotifs++;
if (numNotifs > 0 && (numNotifs % EXPECTED_NUM_POOLS) == 0) { signals.release();
checker.goCheckResult();
}
} }
} }
} }
...@@ -134,6 +141,9 @@ public class CollectionUsageThreshold { ...@@ -134,6 +141,9 @@ public class CollectionUsageThreshold {
} }
try { try {
// This test creates a checker thread responsible for checking
// the low memory notifications. It blocks until a permit
// from the signals semaphore is available.
checker = new Checker("Checker thread"); checker = new Checker("Checker thread");
checker.setDaemon(true); checker.setDaemon(true);
checker.start(); checker.start();
...@@ -148,9 +158,18 @@ public class CollectionUsageThreshold { ...@@ -148,9 +158,18 @@ public class CollectionUsageThreshold {
NotificationEmitter emitter = (NotificationEmitter) mm; NotificationEmitter emitter = (NotificationEmitter) mm;
emitter.addNotificationListener(listener, null, null); emitter.addNotificationListener(listener, null, null);
// The main thread invokes GC to trigger the VM to perform
// low memory detection and then waits until the checker thread
// finishes its work to check for a low-memory notification.
//
// At GC time, VM will issue low-memory notification and invoke
// the listener which will release a permit to the signals semaphore.
// When the checker thread acquires the permit and finishes
// checking the low-memory notification, it will also call
// barrier.await() to signal the main thread to resume its work.
for (int i = 0; i < NUM_GCS; i++) { for (int i = 0; i < NUM_GCS; i++) {
invokeGC(); invokeGC();
checker.waitForCheckResult(); barrier.await();
} }
} finally { } finally {
// restore the default // restore the default
...@@ -166,6 +185,7 @@ public class CollectionUsageThreshold { ...@@ -166,6 +185,7 @@ public class CollectionUsageThreshold {
} }
private static void invokeGC() { private static void invokeGC() {
System.out.println("Calling System.gc()"); System.out.println("Calling System.gc()");
numGCs++; numGCs++;
...@@ -180,8 +200,6 @@ public class CollectionUsageThreshold { ...@@ -180,8 +200,6 @@ public class CollectionUsageThreshold {
} }
static class Checker extends Thread { static class Checker extends Thread {
private Object lock = new Object();
private Object go = new Object();
private boolean checkerReady = false; private boolean checkerReady = false;
private int waiters = 0; private int waiters = 0;
private boolean readyToCheck = false; private boolean readyToCheck = false;
...@@ -190,83 +208,48 @@ public class CollectionUsageThreshold { ...@@ -190,83 +208,48 @@ public class CollectionUsageThreshold {
}; };
public void run() { public void run() {
while (true) { while (true) {
synchronized (lock) { try {
checkerReady = true; signals.acquire(EXPECTED_NUM_POOLS);
try {
lock.wait();
} catch (InterruptedException e) {
// ignore
}
checkResult(); checkResult();
checkerReady = false; } catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (BrokenBarrierException e) {
throw new RuntimeException(e);
} }
} }
} }
private void checkResult() { private void checkResult() throws InterruptedException, BrokenBarrierException {
for (PoolRecord pr : result.values()) { for (PoolRecord pr : result.values()) {
if (pr.getListenerInvokedCount() != numGCs) { if (pr.getListenerInvokedCount() != numGCs) {
throw new RuntimeException("Listeners invoked count = " + fail("Listeners invoked count = " +
pr.getListenerInvokedCount() + " expected to be " + pr.getListenerInvokedCount() + " expected to be " +
numGCs); numGCs);
} }
if (pr.getNotifCount() != numGCs) { if (pr.getNotifCount() != numGCs) {
throw new RuntimeException("Notif Count = " + fail("Notif Count = " +
pr.getNotifCount() + " expected to be " + pr.getNotifCount() + " expected to be " +
numGCs); numGCs);
} }
long count = pr.getPool().getCollectionUsageThresholdCount(); long count = pr.getPool().getCollectionUsageThresholdCount();
if (count != numGCs) { if (count != numGCs) {
throw new RuntimeException("CollectionUsageThresholdCount = " + fail("CollectionUsageThresholdCount = " +
count + " expected to be " + numGCs); count + " expected to be " + numGCs);
} }
if (!pr.getPool().isCollectionUsageThresholdExceeded()) { if (!pr.getPool().isCollectionUsageThresholdExceeded()) {
throw new RuntimeException("isCollectionUsageThresholdExceeded" + fail("isCollectionUsageThresholdExceeded" +
" expected to be true"); " expected to be true");
} }
} }
synchronized (go) { // wait until the main thread is waiting for notification
// wait until the main thread is waiting for notification barrier.await();
while (waiters == 0) { System.out.println("notifying main thread to continue - result checking finished");
try {
go.wait(50);
} catch (InterruptedException e) {
// ignore
}
}
System.out.println(Thread.currentThread().getName() +
" notifying main thread to continue - result checking finished");
go.notify();
}
}
public void goCheckResult() {
System.out.println(Thread.currentThread().getName() +
" notifying to check result");
synchronized (lock) {
while (!checkerReady) {
try {
lock.wait(50);
} catch (InterruptedException e) {
// ignore
}
}
lock.notify();
}
} }
public void waitForCheckResult() { private void fail(String msg) {
System.out.println(Thread.currentThread().getName() + // reset the barrier to cause BrokenBarrierException to avoid hanging
" waiting for result checking finishes"); barrier.reset();
synchronized (go) { throw new RuntimeException(msg);
waiters++;
try {
go.wait();
} catch (InterruptedException e) {
// ignore
}
waiters--;
}
} }
} }
} }
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
# @summary Test CollectionUsageThreshold with concurrent marksweep collector # @summary Test CollectionUsageThreshold with concurrent marksweep collector
# @author Mandy Chung # @author Mandy Chung
# #
# @ignore 6982965
# @run build CollectionUsageThreshold # @run build CollectionUsageThreshold
# @run shell/timeout=300 CollectionUsageThresholdConcMarkSweepGC.sh # @run shell/timeout=300 CollectionUsageThresholdConcMarkSweepGC.sh
# #
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册