From d4eb11928f0aad42531327a0d409f4d558ac76fb Mon Sep 17 00:00:00 2001 From: mchung Date: Tue, 19 Oct 2010 09:49:08 -0700 Subject: [PATCH] 6992968: test/java/lang/management/MemoryMXBean/CollectionUsageThresholdConcMarkSweepGC.sh should not hang Reviewed-by: alanb, dholmes --- .../CollectionUsageThreshold.java | 103 ++++++++---------- ...CollectionUsageThresholdConcMarkSweepGC.sh | 1 + 2 files changed, 44 insertions(+), 60 deletions(-) diff --git a/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java b/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java index b7a04e030..22e1dc165 100644 --- a/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java +++ b/test/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4959889 + * @bug 4959889 6992968 * @summary Basic unit test of memory management testing: * 1) setCollectionUsageThreshold() and getCollectionUsageThreshold() * 2) test notification emitted for two different memory pools. @@ -34,8 +34,10 @@ * @run main/timeout=300 CollectionUsageThreshold */ +import java.lang.Thread.*; import java.lang.management.*; import java.util.*; +import java.util.concurrent.*; import javax.management.*; import javax.management.openmbean.CompositeData; @@ -52,6 +54,12 @@ public class CollectionUsageThreshold { private static Checker checker; 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 { private MemoryPoolMXBean pool; private int listenerInvoked = 0; @@ -98,10 +106,9 @@ public class CollectionUsageThreshold { } pr.addNotification(minfo); synchronized (this) { + System.out.println("notifying the checker thread to check result"); numNotifs++; - if (numNotifs > 0 && (numNotifs % EXPECTED_NUM_POOLS) == 0) { - checker.goCheckResult(); - } + signals.release(); } } } @@ -134,6 +141,9 @@ public class CollectionUsageThreshold { } 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.setDaemon(true); checker.start(); @@ -148,9 +158,18 @@ public class CollectionUsageThreshold { NotificationEmitter emitter = (NotificationEmitter) mm; 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++) { invokeGC(); - checker.waitForCheckResult(); + barrier.await(); } } finally { // restore the default @@ -166,6 +185,7 @@ public class CollectionUsageThreshold { } + private static void invokeGC() { System.out.println("Calling System.gc()"); numGCs++; @@ -180,8 +200,6 @@ public class CollectionUsageThreshold { } static class Checker extends Thread { - private Object lock = new Object(); - private Object go = new Object(); private boolean checkerReady = false; private int waiters = 0; private boolean readyToCheck = false; @@ -190,83 +208,48 @@ public class CollectionUsageThreshold { }; public void run() { while (true) { - synchronized (lock) { - checkerReady = true; - try { - lock.wait(); - } catch (InterruptedException e) { - // ignore - } + try { + signals.acquire(EXPECTED_NUM_POOLS); 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()) { if (pr.getListenerInvokedCount() != numGCs) { - throw new RuntimeException("Listeners invoked count = " + + fail("Listeners invoked count = " + pr.getListenerInvokedCount() + " expected to be " + numGCs); } if (pr.getNotifCount() != numGCs) { - throw new RuntimeException("Notif Count = " + + fail("Notif Count = " + pr.getNotifCount() + " expected to be " + numGCs); } long count = pr.getPool().getCollectionUsageThresholdCount(); if (count != numGCs) { - throw new RuntimeException("CollectionUsageThresholdCount = " + + fail("CollectionUsageThresholdCount = " + count + " expected to be " + numGCs); } if (!pr.getPool().isCollectionUsageThresholdExceeded()) { - throw new RuntimeException("isCollectionUsageThresholdExceeded" + + fail("isCollectionUsageThresholdExceeded" + " expected to be true"); } } - synchronized (go) { - // wait until the main thread is waiting for notification - while (waiters == 0) { - 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(); - } + // wait until the main thread is waiting for notification + barrier.await(); + System.out.println("notifying main thread to continue - result checking finished"); } - public void waitForCheckResult() { - System.out.println(Thread.currentThread().getName() + - " waiting for result checking finishes"); - synchronized (go) { - waiters++; - try { - go.wait(); - } catch (InterruptedException e) { - // ignore - } - waiters--; - } + private void fail(String msg) { + // reset the barrier to cause BrokenBarrierException to avoid hanging + barrier.reset(); + throw new RuntimeException(msg); } } } diff --git a/test/java/lang/management/MemoryMXBean/CollectionUsageThresholdConcMarkSweepGC.sh b/test/java/lang/management/MemoryMXBean/CollectionUsageThresholdConcMarkSweepGC.sh index 3dac6c5d5..6e005a025 100644 --- a/test/java/lang/management/MemoryMXBean/CollectionUsageThresholdConcMarkSweepGC.sh +++ b/test/java/lang/management/MemoryMXBean/CollectionUsageThresholdConcMarkSweepGC.sh @@ -27,6 +27,7 @@ # @summary Test CollectionUsageThreshold with concurrent marksweep collector # @author Mandy Chung # +# @ignore 6982965 # @run build CollectionUsageThreshold # @run shell/timeout=300 CollectionUsageThresholdConcMarkSweepGC.sh # -- GitLab