diff -r 746229cc1ab0 -r cc29d7717e3a test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ClassLoadingController.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ClassLoadingController.java Wed May 02 16:43:56 2018 -0700
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2003, 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.monitoring.share;
+
+import java.util.*;
+import nsk.share.log.Log;
+import nsk.share.ClassUnloader;
+import nsk.share.CustomClassLoader;
+import nsk.share.test.Stresser;
+
+/**
+ * The ClassLoadingController
class allows to operate class
+ * loading/unloading process.
+ */
+public class ClassLoadingController extends StateControllerBase {
+ // Path and name of the classes to load
+ private static final String CLASSNAME_PATTERN = "nsk.monitoring.share.newclass.LoadableClass";
+
+ private int loadedClassCount = 100;
+ private int loaderCount = 1;
+ private boolean singleClass = true;
+ private String classDir;
+ private Hashtable classesTable = new Hashtable();
+ private ClassUnloader[] unloaders;
+
+ private Stresser stresser;
+
+ /**
+ * Constructs a new ClassLoadingController
with defined
+ * arguments.
+ *
+ * @param log Log
to print log info to.
+ * @param loadedClassCount number of classes to load.
+ * @param loaderCount number of loaders to use.
+ * @param singleClass if class loaders are instances of the same class.
+ * @param classDir directory to load classes from.
+ */
+ public ClassLoadingController(
+ Log log,
+ int loadedClassCount,
+ int loaderCount,
+ boolean singleClass,
+ String classDir,
+ Stresser stresser
+ ) {
+ super(log);
+ setLoadedClassCount(loadedClassCount);
+ setLoaderCount(loaderCount);
+ setClassDir(classDir);
+ singleClassLoaderClass(singleClass);
+ dump();
+ preloadAllClasses();
+ setStresser(stresser);
+ }
+
+ private void setStresser(Stresser stresser) {
+ this.stresser = stresser;
+ }
+
+ public ClassLoadingController(Log log, ArgumentHandler argHandler, Stresser stresser) {
+ this(
+ log,
+ argHandler.getLoadableClassesCount(),
+// argHandler.getLoadersCount(),
+ (int)stresser.getMaxIterations(),
+ argHandler.singleClassloaderClass(),
+ argHandler.getRawArgument(0),
+ stresser
+ );
+ }
+
+ public void dump() {
+ log.debug("classes to be loaded:\t" + loadedClassCount);
+ log.debug("classloader instances:\t" + loaderCount);
+ if (singleClass)
+ log.debug("classloader class:\tsingle");
+ else
+ log.debug("classloader class:\ttwo");
+ log.debug("Class dir" + classDir);
+
+ }
+
+ private void setLoadedClassCount(int loadedClassCount) {
+ this.loadedClassCount = loadedClassCount;
+ }
+
+ // Set loaderCount value
+ private void setLoaderCount(int loaderCount) {
+ this.loaderCount = loaderCount;
+ }
+
+ // Set singleClass value
+ private void singleClassLoaderClass(boolean singleClass) {
+ this.singleClass = singleClass;
+ }
+
+ // Set classDir value
+ private void setClassDir(String classDir) {
+ this.classDir = classDir;
+ }
+
+ // Load classes
+ private void preloadAllClasses() {
+ log.debug("preloading all classes...");
+ if (singleClass)
+ createUnloaders(1);
+ else
+ createUnloaders(2);
+
+ for (int i = 0; i < unloaders.length; i++) {
+ loadClasses(unloaders[i], 1, false);
+ unloaders[i].unloadClass();
+ }
+ }
+
+ // Load classes
+ private boolean loadClasses(ClassUnloader unloader, int classCount, boolean doKeep) {
+ String newClassName;
+ String[] classNames = new String[classCount + 1];
+ classNames[0] = unloader.getClassLoader().getClass().getName()
+ + "@"
+ + Integer.toHexString(
+ unloader.getClassLoader().hashCode()
+ );
+
+
+ for (int i = 1; i <= classCount; i++) {
+ newClassName = CLASSNAME_PATTERN + int2Str(i);
+ classNames[i] = newClassName;
+ try {
+ unloader.loadClass(newClassName);
+ } catch (ClassNotFoundException e) {
+ log.error(e.toString());
+ e.printStackTrace();
+ return false;
+ }
+ }
+ if (doKeep)
+ classesTable.put(String.valueOf(unloader.hashCode()), classNames);
+ return true;
+ } // loadClasses()
+
+ /**
+ * Loads all classes.
+ *
+ * @see ClassLoadingController#ClassLoadingController
+ */
+ public int loadClasses() {
+ CustomClassLoader loader;
+ boolean res = true;
+ String loaderName;
+
+ createUnloaders(loaderCount);
+
+ int count = 0;
+ for (int i = 0; i < unloaders.length; i++) {
+ loaderName = unloaders[i].getClassLoader().getClass().getName()
+ + "@"
+ + Integer.toHexString(
+ unloaders[i].getClassLoader().hashCode()
+ );
+ if (loadClasses(unloaders[i], loadedClassCount, true)) {
+ String[] values = (String[])
+ classesTable.get(String.valueOf(unloaders[i].hashCode()));
+ int length = values.length - 1;
+ log.debug(loaderName + "(" + i + ")>>> " + length
+ + " classes have been loaded");
+ count += length;
+ }
+ }
+ log.info("Total: loading is performed " + count + " times");
+
+ return count;
+ }
+
+ // Unload classes
+ public int unloadClasses() {
+ String loaderName;
+ int count = 0;
+ long timeLeft = 0;
+
+ for (int i = 0; i < loaderCount && (timeLeft = stresser.getTimeLeft()/1000) > 0; i++) {
+ loaderName = unloaders[i].getClassLoader().getClass().getName()
+ + "@"
+ + Integer.toHexString(
+ unloaders[i].getClassLoader().hashCode()
+ );
+ String hashCode = String.valueOf(unloaders[i].hashCode());
+ String[] values = (String[]) classesTable.get(hashCode);
+
+ if (unloaders[i].unloadClass()) {
+ int length = values.length - 1;
+ count += length;
+ log.debug(loaderName + "(" + i + ")>>> " + length
+ + " classes have been unloaded (time left: "+timeLeft+" s)");
+ classesTable.remove(hashCode);
+ } else {
+ log.debug(loaderName + "(" + i + ")>>> "
+ + "classes couldn't be unloaded (time left: "+timeLeft+" s)");
+ }
+ }
+
+ log.info("Total: unloading is performed " + count + " times");
+
+ return count;
+ }
+
+ private void createUnloaders(int count) {
+ CustomClassLoader loader;
+ unloaders = new ClassUnloader[count];
+
+ for (int i = 0; i < count; i++) {
+ unloaders[i] = new ClassUnloader();
+ if (singleClass) {
+ loader = unloaders[i].createClassLoader();
+ } else {
+ if (i%2 == 0)
+ loader = new ClassLoaderA();
+ else
+ loader = new ClassLoaderB();
+ unloaders[i].setClassLoader(loader);
+ }
+ loader.setClassPath(classDir);
+ } // for
+ }
+
+ /**
+ * Brings out VM into defined state. The method loads all classes via
+ * {@link ClassLoadingController#loadClasses}.
+ *
+ * @see ClassLoadingController#loadClasses
+ */
+ public void run() {
+ loadClasses();
+ }
+
+ /**
+ * Tries to reclaim VM into initial state. The method tries to load all
+ * classes via {@link ClassLoadingController#unloadClasses}.
+ *
+ * @see ClassLoadingController#unloadClasses
+ */
+ public void reset() {
+ unloadClasses();
+ }
+
+ // The class extends CustomClassLoader with specific implementation of
+ // toString() method
+ class ClassLoaderA extends CustomClassLoader {
+ public ClassLoaderA() {
+ super();
+ }
+
+ public String toString() {
+ return "ClassLoaderA";
+ }
+ } // ClassLoaderA
+
+ // The class extends CustomClassLoader with specific implementation of
+ // toString() method
+ class ClassLoaderB extends CustomClassLoader {
+ public ClassLoaderB() {
+ super();
+ }
+
+ public String toString() {
+ return "ClassLoaderB";
+ }
+ } // ClassLoaderB
+}