8031065: java/lang/management/MemoryMXBean/LowMemoryTest2.sh fails: OutOfMemoryError: Metaspace
authormtobiass
Tue, 04 Mar 2014 09:35:54 +0100
changeset 23053 788f0ea9a703
parent 23052 241885315119
child 23054 9ce297e5f4a2
8031065: java/lang/management/MemoryMXBean/LowMemoryTest2.sh fails: OutOfMemoryError: Metaspace Summary: Load classes until getUsageThresholdCount() > 0 instead of isUsageThresholdExceeded(). Reviewed-by: dfuchs, sjiang, sla
jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest2.java
--- a/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest2.java	Wed Mar 05 07:24:34 2014 +0000
+++ b/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest2.java	Tue Mar 04 09:35:54 2014 +0100
@@ -67,7 +67,7 @@
 
         static int count = 100000;
 
-        Class loadNext() throws ClassNotFoundException {
+        Class loadNext() {
 
             // public class TestNNNNNN extends java.lang.Object{
             // public TestNNNNNN();
@@ -135,63 +135,49 @@
         }
 
         /*
-         * Run method for thread that continuously loads classes.
-         *
-         * Note: Once the usage threshold has been exceeded the low memory
-         * detector thread will attempt to deliver its notification - this can
-         * potentially create a race condition with this thread contining to
-         * fill up metaspace. To avoid the low memory detector getting an
-         * OutOfMemory we throttle this thread once the threshold has been
-         * exceeded.
+         * Load classes until MemoryPoolMXBean.getUsageThresholdCount() > 0.
+         * Then wait for the memory threshold notification to be received.
          */
         public void run() {
-            List pools = ManagementFactory.getMemoryPoolMXBeans();
+            List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
             boolean thresholdExceeded = false;
 
-            for (;;) {
-                try {
-                    // the classes are small so we load 10 at a time
-                    for (int i=0; i<10; i++) {
-                        loadNext();
-                    }
-                } catch (ClassNotFoundException x) {
-                    return;
-                }
-                if (listenerInvoked) {
-                    return;
+            // Load classes until MemoryPoolMXBean.getUsageThresholdCount() > 0
+            while (!thresholdExceeded) {
+                // the classes are small so we load 10 at a time
+                for (int i=0; i<10; i++) {
+                    loadNext();
                 }
 
-                // if threshold has been exceeded we put in a delay to allow
-                // the low memory detector do its job.
-                if (thresholdExceeded) {
-                    try {
-                        Thread.currentThread().sleep(100);
-                    } catch (InterruptedException x) { }
-                } else {
-                    // check if the threshold has been exceeded
-                    ListIterator i = pools.listIterator();
-                    while (i.hasNext()) {
-                        MemoryPoolMXBean p = (MemoryPoolMXBean) i.next();
-                        if (p.getType() == MemoryType.NON_HEAP &&
-                            p.isUsageThresholdSupported())
-                        {
-                            thresholdExceeded = p.isUsageThresholdExceeded();
-                        }
+                // check if the threshold has been exceeded
+                for (MemoryPoolMXBean p : pools) {
+                    if (p.getType() == MemoryType.NON_HEAP &&
+                        p.isUsageThresholdSupported() &&
+                        p.getUsageThresholdCount() > 0)
+                    {
+                        thresholdExceeded = true;
+                        break;
                     }
                 }
             }
+
+            System.out.println("thresholdExceeded. Waiting for notification");
+            while (!listenerInvoked) {
+                try {
+                    Thread.currentThread().sleep(10);
+                } catch (InterruptedException x) {}
+            }
         }
     }
 
     public static void main(String args[]) {
-        ListIterator iter = ManagementFactory.getMemoryPoolMXBeans().listIterator();
+        List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
 
         // Set threshold of 80% of all NON_HEAP memory pools
         // In the Hotspot implementation this means we should get a notification
         // if the CodeCache or metaspace fills up.
 
-        while (iter.hasNext()) {
-            MemoryPoolMXBean p = (MemoryPoolMXBean) iter.next();
+        for (MemoryPoolMXBean p : pools) {
             if (p.getType() == MemoryType.NON_HEAP && p.isUsageThresholdSupported()) {
 
                 // set threshold