[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-serviceability-dev
Subject:    Re: RFR(XS) 8031065: LowMemoryTest2.sh fails: OutOfMemoryError: Metaspace
From:       Mattias Tobiasson <mattias.tobiasson () oracle ! com>
Date:       2014-03-03 17:03:56
Message-ID: 46e29a93-a294-444f-9e66-4bd106d651e6 () default
[Download RAW message or body]

Daniel, could you please sponsor this fix?

Mattias

----- Original Message -----
From: daniel.fuchs@oracle.com
To: mattias.tobiasson@oracle.com, shanliang.jiang@oracle.com
Cc: serviceability-dev@openjdk.java.net
Sent: Friday, February 28, 2014 12:05:47 PM GMT +01:00 Amsterdam / Berlin / Bern / \
                Rome / Stockholm / Vienna
Subject: Re: RFR(XS) 8031065: LowMemoryTest2.sh fails: OutOfMemoryError: Metaspace

Hi Mattias,

The new version looks good!

best regards,

-- daniel

On 2/28/14 11:33 AM, Mattias Tobiasson wrote:
> Hi,
> I have updated the test and now stop allocating when we have reached the threshold.
> Since we now do all allocations first and then just wait for the notification, I \
> have split the loop into two separate loops to make it clearer. 
> To detect if we have reached the threshold I now check \
> MemoryPoolMXBean.getUsageThresholdCount() > 0 instead of checking \
> isUsageThresholdExceeded(). The reason for that is because the notification event \
> is not generated immediately when isUsageThresholdExceeded() = true. The \
> notification is only generated at the next GC. So that is the reason for why the \
> old test kept allocating after it had reached the threshold (to trigger another \
> GC). 
> getUsageThresholdCount() is updated at the same time as the event is generated. So \
> after getUsageThresholdCount() > 0, I can just wait for the notification without \
> more allocations. 
> webrev:
> http://cr.openjdk.java.net/~mtobiass/8031065/webrev.01
> 
> bug:
> https://bugs.openjdk.java.net/browse/JDK-8031065
> 
> Mattias
> 
> ----- Original Message -----
> From: shanliang.jiang@oracle.com
> To: mattias.tobiasson@oracle.com
> Cc: serviceability-dev@openjdk.java.net, daniel.fuchs@oracle.com
> Sent: Thursday, February 27, 2014 5:12:51 PM GMT +01:00 Amsterdam / Berlin / Bern / \
>                 Rome / Stockholm / Vienna
> Subject: Re: RFR(XS) 8031065: LowMemoryTest2.sh fails: OutOfMemoryError: Metaspace
> 
> 
> Mattias Tobiasson wrote:
> 
> Hi, thanks for the fast reviews.
> 
> I did think about stop calling loadNext() after the flag has been set. The main \
> reason for not doing that was just because I wanted to change as little as \
> possible. Now the test works as originally intended. I prefer to do like this too \
> :) 
> 
> I do not mind removing the calls to loadNext(), but then we would need some timeout \
> waiting for the callback. Currently the test "times out" with an OutOfMemory when \
> we have allocated the remaining 20% of the space. You do not need to add a timeout, \
> only change Line 151 for(;;)
> to
> while(!listenerInvoked) {
> 
> and remove 160 -- 162
> 
> in case that an expected notification is not arrived, the testing harness has a \
> timeout to stop the test. 
> This way makes the test more robust, but I am OK with the current fix.
> 
> Thanks,
> Shanliang
> 
> 
> About line 172, you are correct. I will just remove that line. Thanks!
> 
> Mattias
> 
> ----- Original Message -----
> From: shanliang.jiang@oracle.com To: daniel.fuchs@oracle.com Cc: \
> mattias.tobiasson@oracle.com , serviceability-dev@openjdk.java.net Sent: Thursday, \
> February 27, 2014 12:59:49 PM GMT +01:00 Amsterdam / Berlin / Bern / Rome / \
>                 Stockholm / Vienna
> Subject: Re: RFR(XS) 8031065: LowMemoryTest2.sh fails: OutOfMemoryError: Metaspace
> 
> Daniel Fuchs wrote:
> 
> On 2/27/14 11:43 AM, Mattias Tobiasson wrote:
> 
> Hi,
> Could you please review this test fix.
> 
> The test verifies that MemoryPoolMXBean sends a notification when
> used memory has reached the threshold.
> The flag thresholdExceeded marks if we have reached the memory
> threshold. When the flag is set, the test slows down to give time for
> the notification to be received.
> The problem is that thresholdExceeded is overwritten every time in
> the loop. Instead it should be set if any pool has reached the
> threshold. This means that the test continues to allocate memory at
> full speed, and we may get an OutOfMemory before we get the
> notification. Hi Mattias,
> 
> I wonder whether you should also stop calling loadNext() once
> thresholdExceeded is true? Yes I am thinking this too.
> 
> Line 172 is unnecessary, after thresholdExceeded becomes true, Line 170
> will always be skipped.
> 
> Shanliang
> 
> best regards,
> 
> -- daniel
> 
> bug: https://bugs.openjdk.java.net/browse/JDK-8031065 webrev: \
> http://cr.openjdk.java.net/~ykantser/8031065/webrev.00/ Mattias 


["8031065.patch" (text/x-patch)]

# HG changeset patch
# User mtobiass
# Date 1393582400 -3600
# Node ID 6b98516e31343740f7d24bbcb939deef1a0fb2a2
# Parent  0731952efb104b783b75a5765a91a91601903a3c
8031065: java/lang/management/MemoryMXBean/LowMemoryTest2.sh fails: OutOfMemoryError: \
                Metaspace
Summary: Load classes until getUsageThresholdCount() > 0 instead of \
                isUsageThresholdExceeded().
Contributed-by: mattias.tobiasson@oracle.com

diff --git a/test/java/lang/management/MemoryMXBean/LowMemoryTest2.java \
                b/test/java/lang/management/MemoryMXBean/LowMemoryTest2.java
--- a/test/java/lang/management/MemoryMXBean/LowMemoryTest2.java
+++ b/test/java/lang/management/MemoryMXBean/LowMemoryTest2.java
@@ -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



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic