8208697: vmTestbase/metaspace/stressHierarchy/stressHierarchy012/TestDescription.java fails with OutOfMemoryError: Metaspace
authorcoleenp
Mon, 10 Sep 2018 16:33:55 -0400
changeset 51686 b8b0da4a5f49
parent 51685 1f70116be2df
child 51687 1e39953aaed8
8208697: vmTestbase/metaspace/stressHierarchy/stressHierarchy012/TestDescription.java fails with OutOfMemoryError: Metaspace Summary: remove timeoutHandler class and let Stresser handle timeout, remove 30 threads filling metaspace, and remove related unused files. Reviewed-by: lfoltan, mseledtsov
test/hotspot/jtreg/ProblemList.txt
test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/PerformChecksHelper.java
test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/StressHierarchyBaseClass.java
test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/stressHierarchy012/TestDescription.java
test/hotspot/jtreg/vmTestbase/nsk/share/classload/GeneratingClassLoader.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/timeoutwatchdog/TimeoutHandler.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/timeoutwatchdog/TimeoutWatchdog.java
test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingByFillingHeap.java
test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingByFillingMetaspace.java
test/hotspot/jtreg/vmTestbase/vm/share/vmstresser/CompileAndDeoptimize.java
test/hotspot/jtreg/vmTestbase/vm/share/vmstresser/MetaspaceStresser.java
--- a/test/hotspot/jtreg/ProblemList.txt	Mon Sep 10 12:48:57 2018 -0700
+++ b/test/hotspot/jtreg/ProblemList.txt	Mon Sep 10 16:33:55 2018 -0400
@@ -214,11 +214,4 @@
 
 vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java 7199837 generic-all
 
-vmTestbase/metaspace/stressHierarchy/stressHierarchy007/TestDescription.java 8208697 generic-all
-vmTestbase/metaspace/stressHierarchy/stressHierarchy008/TestDescription.java 8208697 generic-all
-vmTestbase/metaspace/stressHierarchy/stressHierarchy009/TestDescription.java 8208697 generic-all
-vmTestbase/metaspace/stressHierarchy/stressHierarchy010/TestDescription.java 8208697 generic-all
-vmTestbase/metaspace/stressHierarchy/stressHierarchy011/TestDescription.java 8208697 generic-all
-vmTestbase/metaspace/stressHierarchy/stressHierarchy012/TestDescription.java 8208697 generic-all
-
 #############################################################################
--- a/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/PerformChecksHelper.java	Mon Sep 10 12:48:57 2018 -0700
+++ b/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/PerformChecksHelper.java	Mon Sep 10 16:33:55 2018 -0400
@@ -137,10 +137,10 @@
                 }
             }
         } catch (OutOfMemoryError e) {
-            if (e.getMessage().trim().toLowerCase().contains("metadata")) {
-                System.out.println("Got OOME in metaspace in PerformChecksHelper.callMethods(Class clazz). " +
-                                "This happened because reflection generates a too many accessors. " +
-                                "There is nothing we can do with it, so we are just suppressing.");
+            if (e.getMessage().trim().toLowerCase().contains("metaspace")) {
+                // avoid string concatenation, which may create more classes.
+                System.out.println("Got OOME in metaspace in PerformChecksHelper.callMethods(Class clazz). ");
+                System.out.println("This is possible with -triggerUnloadingByFillingMetaspace");
             } else {
                 throw e;
             }
--- a/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/StressHierarchyBaseClass.java	Mon Sep 10 12:48:57 2018 -0700
+++ b/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/StressHierarchyBaseClass.java	Mon Sep 10 16:33:55 2018 -0400
@@ -39,15 +39,13 @@
 import nsk.share.test.ExecutionController;
 import nsk.share.test.Stresser;
 import nsk.share.test.TestBase;
-import nsk.share.test.timeoutwatchdog.TimeoutHandler;
-import nsk.share.test.timeoutwatchdog.TimeoutWatchdog;
 
 
 /**
  * Superclass for StressHierarchy* tests. It provides util methods to create and load
  * classes hierarchy and perform checks.
  */
-abstract public class StressHierarchyBaseClass extends TestBase implements TimeoutHandler {
+abstract public class StressHierarchyBaseClass extends TestBase {
 
     protected static String[] args;
 
@@ -101,7 +99,6 @@
             long startTimeStamp = System.currentTimeMillis();
             ExecutionController stresser = new Stresser(args);
             stresser.start(1);
-            TimeoutWatchdog.watch(stresser, this);
             TreeDescriptor treeDescriptor = GenerateHierarchyHelper.generateHierarchy(treeDepth, minLevelSize, maxLevelSize, hierarchyType);
             Tree tree = buildTree(treeDescriptor);
             System.out.println("Generating took " + ((System.currentTimeMillis() - startTimeStamp)/1000) +" sec");
@@ -128,12 +125,6 @@
         }
     }
 
-    @Override
-    public void handleTimeout() {
-        System.out.println("Shutting down vm because of time expired.");
-        System.exit(95);
-    }
-
     abstract protected void runTestLogic(Tree tree, ExecutionController stresser) throws Throwable;
 
     private Tree buildTree(TreeDescriptor treeDescriptor) throws MalformedURLException,
--- a/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/stressHierarchy012/TestDescription.java	Mon Sep 10 12:48:57 2018 -0700
+++ b/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/stressHierarchy012/TestDescription.java	Mon Sep 10 16:33:55 2018 -0400
@@ -37,7 +37,7 @@
  * @comment generate and compile metaspace.stressHierarchy.common.HumongousClass
  * @run driver metaspace.stressHierarchy.common.GenClassesBuilder
  * @run main/othervm
- *      -XX:MaxMetaspaceSize=450m
+ *      -XX:MaxMetaspaceSize=250m
  *      -Xss10m
  *      -Xbootclasspath/a:.
  *      -XX:+UnlockDiagnosticVMOptions
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/classload/GeneratingClassLoader.java	Mon Sep 10 12:48:57 2018 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/classload/GeneratingClassLoader.java	Mon Sep 10 16:33:55 2018 -0400
@@ -119,8 +119,6 @@
                         return bytecode;
                 } catch (UnsupportedEncodingException e) {
                         throw new TestBug(e);
-                } catch (IOException e) {
-                        throw new TestBug(e);
                 }
         }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/test/timeoutwatchdog/TimeoutHandler.java	Mon Sep 10 12:48:57 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package nsk.share.test.timeoutwatchdog;
-
-/**
- * TimeoutHandler - interface to define reaction on timeout.
- * @see TimeoutWatchdoc
- */
-public interface TimeoutHandler {
-
-        /**
-         * Invoked when watchdog detects timeout. Subclasses must implement this method to define how timeout should be handled.
-         */
-        void handleTimeout();
-
-}
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/test/timeoutwatchdog/TimeoutWatchdog.java	Mon Sep 10 12:48:57 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package nsk.share.test.timeoutwatchdog;
-
-import nsk.share.test.ExecutionController;
-
-/**
- * This class watches for ExecutionControler and notifies TimeoutHander in case of timeout.
- */
-public class TimeoutWatchdog implements Runnable {
-
-        private ExecutionController executionController;
-
-        private TimeoutHandler handler;
-
-        private static long CHECK_PERIOD = 1000; // In milliseconds
-
-        private TimeoutWatchdog(ExecutionController executionController, TimeoutHandler handler) {
-                this.executionController = executionController;
-                this.handler = handler;
-        }
-
-        /**
-         * Start watching for timeout.
-         * This method runs a new daemon thread that checks periodically if the observable test is still running.
-         * If timeout is detected <code>handler.handleTimeout()</code> will be called. If the test finishes normally the daemon
-         * thread will silently die.
-         * @param executionController - executionController used to monitor time left
-         * @param handler - handler on which handleTimeout() will be called
-         */
-        public static void watch(ExecutionController executionController, TimeoutHandler handler) {
-                Thread thread = new Thread(new TimeoutWatchdog(executionController, handler));
-                thread.setName("TimeoutWatchdog_thread");
-                thread.setDaemon(true);
-                thread.start();
-        }
-
-        @Override
-        public void run() {
-                try {
-                        while (true) {
-                                Thread.sleep(CHECK_PERIOD);
-                                if (!executionController.continueExecution()) {
-                                        System.out.println("Time expired. TimeoutWatchdog is calling TimeoutHandler.handleTimeout.");
-                                        handler.handleTimeout();
-                                }
-                        }
-                } catch (InterruptedException e) {
-                        throw new RuntimeException("Somebody dared to interrupt TimeoutWatchdog thread.");
-                }
-        }
-
-}
--- a/test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingByFillingHeap.java	Mon Sep 10 12:48:57 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package vm.share.gc;
-
-import java.lang.management.ManagementFactory;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
-import nsk.share.TestFailure;
-import nsk.share.test.ExecutionController;
-
-public class TriggerUnloadingByFillingHeap implements TriggerUnloadingHelper {
-
-    public void triggerUnloading(ExecutionController stresser) {
-        List<String> jvmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
-        if (jvmArgs.contains("-XX:+ExplicitGCInvokesConcurrent")) {
-                throw new TestFailure("Test bug! Found -XX:+ExplicitGCInvokesConcurrent in jvm args. TriggerUnloadingByFillingHeap.triggerUnloading will not work!.");
-        }
-
-        System.out.println("collections invoked: " + provokeGC(stresser));
-        System.out.println("collections invoked: " + provokeGC(stresser));
-        System.out.println("collections invoked: " + provokeGC(stresser));
-    }
-
-    private static long getGCCounter() {
-        return ManagementFactory.getGarbageCollectorMXBeans().get(1).getCollectionCount();
-    }
-
-    private static Random random = new Random();
-
-    public static byte[] garbage; //make it reference public to avoid compiler optimizations
-
-    private static long provokeGC(ExecutionController stresser) {
-        long initCounter = getGCCounter();
-        ArrayList<byte[]> list = new ArrayList<byte[]>();
-        while (getGCCounter() == initCounter && stresser.continueExecution()) {
-            list.add(new byte[1024]);
-
-            garbage = new byte[1024];
-            if (random.nextInt(10) % 10 < 3 && !list.isEmpty()) {
-                list.remove(0);
-            }
-            System.gc();
-        }
-        return getGCCounter() - initCounter;
-    }
-
-}
--- a/test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingByFillingMetaspace.java	Mon Sep 10 12:48:57 2018 -0700
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingByFillingMetaspace.java	Mon Sep 10 16:33:55 2018 -0400
@@ -22,76 +22,38 @@
  */
 package vm.share.gc;
 
-import java.util.ArrayList;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
+import nsk.share.test.ExecutionController;
 import metaspace.stressHierarchy.common.exceptions.GotWrongOOMEException;
 import nsk.share.gc.gp.classload.GeneratedClassProducer;
-import nsk.share.test.ExecutionController;
 
 public class TriggerUnloadingByFillingMetaspace implements
         TriggerUnloadingHelper {
 
-    private static final int NUMBER_OF_THREADS = 30;
-
-    private static class FillMetaspace {
-        private volatile boolean gotOOME = false;
-        private ExecutionController stresser;
-        private final ThreadLocal<GeneratedClassProducer> generatedClassProducer =
-            new ThreadLocal<GeneratedClassProducer>() {
-              @Override
-              protected GeneratedClassProducer initialValue() {
-                return new GeneratedClassProducer("metaspace.stressHierarchy.common.HumongousClass");
-              }
-            };
-
-        public FillMetaspace(ExecutionController stresser) { this.stresser = stresser; }
+    private volatile boolean gotOOME = false;
+    private ExecutionController stresser;
+    private final ThreadLocal<GeneratedClassProducer> generatedClassProducer =
+        new ThreadLocal<GeneratedClassProducer>() {
+          @Override
+          protected GeneratedClassProducer initialValue() {
+            return new GeneratedClassProducer("metaspace.stressHierarchy.common.HumongousClass");
+          }
+        };
 
-        private class FillMetaspaceTask implements Callable<Object> {
-            @Override
-            public Object call() throws Exception {
-                while (stresser.continueExecution() && ! gotOOME) {
-                    try {
-                        generatedClassProducer.get().create(-100500); //argument is not used.
-                    } catch (OutOfMemoryError oome) {
-                        if (!isInMetaspace(oome)) {
-                            throw new GotWrongOOMEException("Got OOME in heap while gaining OOME in metaspace. Test result can't be valid.");
-                        }
-                        gotOOME = true;
-                    }
-                }
-                return null;
-            }
-        }
-    }
-
-    private static boolean isInMetaspace(OutOfMemoryError error) {
-        return error.getMessage().trim().toLowerCase().contains("metadata");
+    private static boolean isInMetaspace(Throwable error) {
+        return (error.getMessage().trim().toLowerCase().contains("metaspace"));
     }
 
     @Override
     public void triggerUnloading(ExecutionController stresser) {
-        try {
-            FillMetaspace fillMetaspace = new FillMetaspace(stresser);
-            ArrayList<Callable<Object>> tasks = new ArrayList<Callable<Object>>(NUMBER_OF_THREADS);
-            for (int i = 0; i < NUMBER_OF_THREADS; i++) {
-                tasks.add(fillMetaspace.new FillMetaspaceTask());
-            }
-            ExecutorService executorService = Executors.newCachedThreadPool();
+        while (stresser.continueExecution() && !gotOOME) {
             try {
-                executorService.invokeAll(tasks);
-            } catch (InterruptedException e) {
-                System.out.println("Process of gaining OOME in metaspace was interrupted.");
-                e.printStackTrace();
+                generatedClassProducer.get().create(-100500); //argument is not used.
+            } catch (Throwable oome) {
+                if (!isInMetaspace(oome)) {
+                    throw new GotWrongOOMEException("Got OOME in heap while triggering OOME in metaspace. Test result can't be valid.");
+                }
+                gotOOME = true;
             }
-        } catch (OutOfMemoryError e) {
-            if (!isInMetaspace(e)) {
-                throw new GotWrongOOMEException("Got OOME in heap while gaining OOME in metaspace. Test result can't be valid.");
-            }
-            return;
         }
     }
-
 }
--- a/test/hotspot/jtreg/vmTestbase/vm/share/vmstresser/CompileAndDeoptimize.java	Mon Sep 10 12:48:57 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package vm.share.vmstresser;
-
-public class CompileAndDeoptimize implements Runnable {
-
-    public static int v = 0;
-
-    private abstract static class A {
-        public abstract void incv();
-    }
-
-    private static class B extends A {
-        public void incv() {
-            v++;
-        }
-    }
-
-    public static class C extends A {
-        public void incv() {
-            v += (new int[1][1][1][1][1][1][1][1]).length;
-        }
-    }
-
-    private volatile boolean done = false;
-    public volatile A a = new B();
-
-    private void incv() {
-        a.incv();
-    }
-
-    private void inc() {
-        while ( ! done ) {
-            incv();
-        }
-        //while ( ! done ) {
-        //      incv();
-        //}
-        //while ( ! done ) {
-        //      incv();
-        //}
-    }
-
-    public void run() {
-        try {
-            Thread t = new Thread(new Runnable() { @Override public void run() { inc(); } });
-            t.start();
-            Thread.sleep(100);
-            a = (A) CompileAndDeoptimize.class.getClassLoader().loadClass(B.class.getName().replaceAll("B$", "C")).getConstructors()[0].newInstance(new Object[0]);
-            //Thread.sleep(1000);
-            //done = true;
-            //t.join();
-
-        } catch ( Throwable t ) {
-            t.printStackTrace();
-        }
-    }
-
-}
--- a/test/hotspot/jtreg/vmTestbase/vm/share/vmstresser/MetaspaceStresser.java	Mon Sep 10 12:48:57 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,260 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package vm.share.vmstresser;
-
-import java.util.*;
-import java.util.concurrent.locks.*;
-
-import nsk.share.*;
-import nsk.share.classload.*;
-import nsk.share.test.*;
-
-/**
- * Stresser that load classes until OOME, then unload some of them and continue loading.
- */
-public class MetaspaceStresser extends Thread {
-
-    /**
-     * Capacity of class containers.
-     * This amount of classes will be unloaded on reset call.
-     */
-    public static final int DEFAULT_BUCKET_SIZE = 4000;
-
-    public static final int DEFAULT_PAUSE_TIME = 0;
-
-    /*
-     * Loaded classes stored in ClassContainer instances.
-     * Such instances organized in array-based stack as it is
-     * one of the simplest way to minimize possibility
-     * to get OOME and guarntee that after replacing
-     * reference to class container by null there will be
-     * no cached refereces and container will be reclaimed by
-     * GC and classes will become unloadable.
-     */
-    // Maximum available amount of arrays with class containers.
-    private static final int CONTAINERS_ARRAY_LENGTH = 1000;
-    // Maximum length array with class containers.
-    private static final int CONTAINER_ARRAYS_COUNT = 100;
-
-    private ClassContainersStack containersStack = new ClassContainersStack(CONTAINER_ARRAYS_COUNT * CONTAINERS_ARRAY_LENGTH,
-            CONTAINERS_ARRAY_LENGTH);
-    private ClassContainer newContainer = null;
-
-    private ExecutionController controller = null;
-    private int bucketSize = DEFAULT_BUCKET_SIZE;
-    private int pauseTime = DEFAULT_PAUSE_TIME;
-
-    private ReentrantLock lock = new ReentrantLock();
-
-    /**
-     * Construct MetaspaceStrresser with default bucket size
-     * and pause time.
-     * @param c controller to control execution time.
-     */
-    public MetaspaceStresser(ExecutionController c) {
-        controller = c;
-    }
-
-    /**
-     * Construct MetaspaceStrresser with custom bucket size
-     * and pause time.
-     * @param c controller to control execution time.
-     * @param bucketSize classes to be unloaded on reset.
-     * @param pauseTime pause after reset.
-     */
-    public MetaspaceStresser(ExecutionController c, int bucketSize, int pauseTime) {
-        this(c);
-        this.bucketSize = bucketSize;
-        this.pauseTime = pauseTime;
-    }
-
-    /**
-     *  Fill Metaspace with classes.
-     *  Classes will be loaded until OOME, then some of them will be unloaded.
-     */
-    public synchronized void prepare() {
-        while (controller.continueExecution()) {
-            try {
-                fillContainerStack();
-            } catch (OutOfMemoryError oome) {
-                unloadLastClassBucket();
-                return;
-            } catch (ClassNotFoundException cnfe) {
-                throw new TestBug("Unexpected exception in stresser.", cnfe);
-            }
-        }
-    }
-
-    /**
-     * Load new class to container, fill containerStack.
-     * Classes will be loaded until OOME
-     * @throws ClassNotFoundException
-     */
-    private void fillContainerStack() throws ClassNotFoundException {
-        newContainer = new ClassContainer();
-        while (newContainer.size() < bucketSize && controller.continueExecution()) {
-            newContainer.loadClass();
-        }
-        containersStack.push(newContainer);
-        newContainer = null;
-    }
-
-    /**
-     * Run stresser.
-     * Stresser will load classes until OOME, then bucketSize classes
-     * will be unloaded and stresser will wait pauseTime millisiconds
-     * before continuing class loading.
-     */
-    public void run() {
-        try {
-            while (controller.continueExecution()) {
-                try {
-                    fillContainerStack();
-                } catch (OutOfMemoryError oome) {
-                    unloadLastClassBucket();
-                    try {
-                        Thread.sleep(pauseTime);
-                    } catch (InterruptedException ie) {
-                    }
-                }
-            }
-        } catch (Throwable e) {
-            throw new TestBug("Unexpected exception in stresser.", e);
-        } finally {
-            containersStack.free();
-        }
-    }
-
-    /**
-     * Unload most recently loaded bucket of classes.
-     */
-    public void unloadLastClassBucket() {
-        while (controller.continueExecution()) {
-            try {
-                containersStack.pop();
-                System.gc();
-                break;
-            } catch (OutOfMemoryError oome) {
-                oome.printStackTrace();
-                continue;
-            }
-        }
-    }
-
-    /**
-     * Array-based stack for ClassContainer's.
-     */
-    private class ClassContainersStack {
-
-        private int arrayLength = 0;
-        private int arraysCount = 0;
-        private int arrayIndex = 0;
-        private int elemIndex = 0;
-
-        private ClassContainer data[][];
-
-        /**
-         * Create ClassContainersStack that will be able
-         * to store size classes in arrays of segmentSize length.
-         */
-        public ClassContainersStack(int size, int segementSize) {
-            arrayLength = segementSize;
-            arraysCount = size / arrayLength;
-            data = new ClassContainer[arraysCount][];
-            data[0] = new ClassContainer[arrayLength];
-        }
-
-        /**
-         * Push ClassContainer c into stack.
-         */
-        public synchronized void push(ClassContainer c) {
-            data[arrayIndex][elemIndex] = c;
-            elemIndex++;
-            if (elemIndex == arrayLength) {
-                if (arrayIndex == arraysCount) {
-                    throw new TestBug("ClassContainersStack ran out of available slots");
-                }
-                data[arrayIndex + 1] = new ClassContainer[arrayLength];
-                arrayIndex++;
-                elemIndex = 0;
-            }
-        }
-
-        /**
-         * Remove reference to top ClassContainer.
-         */
-        public synchronized void pop() {
-            data[arrayIndex][elemIndex] = null;
-            if (elemIndex > 0) {
-                elemIndex--;
-            } else if (arrayIndex > 0) {
-                data[arrayIndex] = null;
-                arrayIndex--;
-                elemIndex = arrayLength - 1;
-            }
-        }
-
-        /**
-         * Remove all stored ClassContainers.
-         */
-        public synchronized void free() {
-            data = null;
-            System.gc();
-            data = new ClassContainer[arraysCount][];
-            data[0] = new ClassContainer[arrayLength];
-            arrayIndex = 0;
-            elemIndex = 0;
-        }
-
-    }
-
-    /// Variable used to create uniqe name for generated classes.
-    private static long lastClass = 0;
-
-    /**
-     * Class container consists of classes and their ClassLoader, so
-     * if there will be no references to container and classes inside it then
-     * it could be easely collected by GC.
-     */
-    private class ClassContainer {
-
-        private List<Class> classes = new LinkedList<Class>();
-        private GeneratingClassLoader loader = new GeneratingClassLoader();
-        private String prefix = loader.getPrefix();
-        private int length = loader.getNameLength();
-
-        public void loadClass() throws ClassNotFoundException {
-            String newName = prefix + "c" + lastClass;
-            lastClass++;
-            while (newName.length() < length) {
-                newName = newName + "c";
-            }
-            classes.add(loader.loadClass(newName));
-        }
-
-        public int size() {
-            return classes.size();
-        }
-    }
-
-}