Daniel, could you please sponsor this fix? Mattias
----- Original Message ----- From: daniel.fu...@oracle.com To: mattias.tobias...@oracle.com, shanliang.ji...@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.ji...@oracle.com > To: mattias.tobias...@oracle.com > Cc: serviceability-dev@openjdk.java.net, daniel.fu...@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.ji...@oracle.com To: daniel.fu...@oracle.com Cc: > mattias.tobias...@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 >
# 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.tobias...@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