Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ClassLoadingController.java
40948 views
/*1* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package nsk.monitoring.share;2425import java.util.*;26import nsk.share.log.Log;27import nsk.share.ClassUnloader;28import nsk.share.CustomClassLoader;29import nsk.share.test.Stresser;3031/**32* The <code>ClassLoadingController</code> class allows to operate class33* loading/unloading process.34*/35public class ClassLoadingController extends StateControllerBase {36// Path and name of the classes to load37private static final String CLASSNAME_PATTERN = "nsk.monitoring.share.newclass.LoadableClass";3839private int loadedClassCount = 100;40private int loaderCount = 1;41private boolean singleClass = true;42private String classDir;43private Hashtable<String, String[]> classesTable = new Hashtable<String, String[]>();44private ClassUnloader[] unloaders;4546private Stresser stresser;4748/**49* Constructs a new <code>ClassLoadingController</code> with defined50* arguments.51*52* @param log <code>Log</code> to print log info to.53* @param loadedClassCount number of classes to load.54* @param loaderCount number of loaders to use.55* @param singleClass if class loaders are instances of the same class.56* @param classDir directory to load classes from.57*/58public ClassLoadingController(59Log log,60int loadedClassCount,61int loaderCount,62boolean singleClass,63String classDir,64Stresser stresser65) {66super(log);67setLoadedClassCount(loadedClassCount);68setLoaderCount(loaderCount);69setClassDir(classDir);70singleClassLoaderClass(singleClass);71dump();72preloadAllClasses();73setStresser(stresser);74}7576private void setStresser(Stresser stresser) {77this.stresser = stresser;78}7980public ClassLoadingController(Log log, ArgumentHandler argHandler, Stresser stresser) {81this(82log,83argHandler.getLoadableClassesCount(),84// argHandler.getLoadersCount(),85(int)stresser.getMaxIterations(),86argHandler.singleClassloaderClass(),87argHandler.getRawArgument(0),88stresser89);90}9192public void dump() {93log.debug("classes to be loaded:\t" + loadedClassCount);94log.debug("classloader instances:\t" + loaderCount);95if (singleClass)96log.debug("classloader class:\tsingle");97else98log.debug("classloader class:\ttwo");99log.debug("Class dir" + classDir);100101}102103private void setLoadedClassCount(int loadedClassCount) {104this.loadedClassCount = loadedClassCount;105}106107// Set loaderCount value108private void setLoaderCount(int loaderCount) {109this.loaderCount = loaderCount;110}111112// Set singleClass value113private void singleClassLoaderClass(boolean singleClass) {114this.singleClass = singleClass;115}116117// Set classDir value118private void setClassDir(String classDir) {119this.classDir = classDir;120}121122// Load classes123private void preloadAllClasses() {124log.debug("preloading all classes...");125if (singleClass)126createUnloaders(1);127else128createUnloaders(2);129130for (int i = 0; i < unloaders.length; i++) {131loadClasses(unloaders[i], 1, false);132unloaders[i].unloadClass();133}134}135136// Load classes137private boolean loadClasses(ClassUnloader unloader, int classCount, boolean doKeep) {138String newClassName;139String[] classNames = new String[classCount + 1];140classNames[0] = unloader.getClassLoader().getClass().getName()141+ "@"142+ Integer.toHexString(143unloader.getClassLoader().hashCode()144);145146147for (int i = 1; i <= classCount; i++) {148newClassName = CLASSNAME_PATTERN + int2Str(i);149classNames[i] = newClassName;150try {151unloader.loadClass(newClassName);152} catch (ClassNotFoundException e) {153log.error(e.toString());154e.printStackTrace();155return false;156}157}158if (doKeep)159classesTable.put(String.valueOf(unloader.hashCode()), classNames);160return true;161} // loadClasses()162163/**164* Loads all classes.165*166* @see ClassLoadingController#ClassLoadingController167*/168public int loadClasses() {169CustomClassLoader loader;170boolean res = true;171String loaderName;172173createUnloaders(loaderCount);174175int count = 0;176for (int i = 0; i < unloaders.length; i++) {177loaderName = unloaders[i].getClassLoader().getClass().getName()178+ "@"179+ Integer.toHexString(180unloaders[i].getClassLoader().hashCode()181);182if (loadClasses(unloaders[i], loadedClassCount, true)) {183String[] values = (String[])184classesTable.get(String.valueOf(unloaders[i].hashCode()));185int length = values.length - 1;186log.debug(loaderName + "(" + i + ")>>> " + length187+ " classes have been loaded");188count += length;189}190}191log.info("Total: loading is performed " + count + " times");192193return count;194}195196// Unload classes197public int unloadClasses() {198String loaderName;199int count = 0;200long timeLeft = 0;201202for (int i = 0; i < loaderCount && (timeLeft = stresser.getTimeLeft()/1000) > 0; i++) {203loaderName = unloaders[i].getClassLoader().getClass().getName()204+ "@"205+ Integer.toHexString(206unloaders[i].getClassLoader().hashCode()207);208String hashCode = String.valueOf(unloaders[i].hashCode());209String[] values = (String[]) classesTable.get(hashCode);210211if (unloaders[i].unloadClass()) {212int length = values.length - 1;213count += length;214log.debug(loaderName + "(" + i + ")>>> " + length215+ " classes have been unloaded (time left: "+timeLeft+" s)");216classesTable.remove(hashCode);217} else {218log.debug(loaderName + "(" + i + ")>>> "219+ "classes couldn't be unloaded (time left: "+timeLeft+" s)");220}221}222223log.info("Total: unloading is performed " + count + " times");224225return count;226}227228private void createUnloaders(int count) {229CustomClassLoader loader;230unloaders = new ClassUnloader[count];231232for (int i = 0; i < count; i++) {233unloaders[i] = new ClassUnloader();234if (singleClass) {235loader = unloaders[i].createClassLoader();236} else {237if (i%2 == 0)238loader = new ClassLoaderA();239else240loader = new ClassLoaderB();241unloaders[i].setClassLoader(loader);242}243loader.setClassPath(classDir);244} // for245}246247/**248* Brings out VM into defined state. The method loads all classes via249* {@link ClassLoadingController#loadClasses}.250*251* @see ClassLoadingController#loadClasses252*/253public void run() {254loadClasses();255}256257/**258* Tries to reclaim VM into initial state. The method tries to load all259* classes via {@link ClassLoadingController#unloadClasses}.260*261* @see ClassLoadingController#unloadClasses262*/263public void reset() {264unloadClasses();265}266267// The class extends CustomClassLoader with specific implementation of268// toString() method269class ClassLoaderA extends CustomClassLoader {270public ClassLoaderA() {271super();272}273274public String toString() {275return "ClassLoaderA";276}277} // ClassLoaderA278279// The class extends CustomClassLoader with specific implementation of280// toString() method281class ClassLoaderB extends CustomClassLoader {282public ClassLoaderB() {283super();284}285286public String toString() {287return "ClassLoaderB";288}289} // ClassLoaderB290}291292293