Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java
41161 views
/*1* Copyright (c) 2006, 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*/2223// THIS TEST IS LINE NUMBER SENSITIVE2425package nsk.share.jpda;2627import java.io.*;28import java.util.*;29import nsk.share.*;30import nsk.share.test.*;31import java.lang.management.GarbageCollectorMXBean;32import java.lang.management.ManagementFactory;33/*34* Class can be used as base debuggee class in jdi and jdwp tests.35* Class contains common method for initializing log, pipe, vm, and several common auxiliary methods. Subclass should implement parseCommand() and, if needed, doInit(parse command line parameters)36* !!! Edit carefully, value of 'DEFAULT_BREAKPOINT_LINE' is hardcoded !!!37*/38public class AbstractDebuggeeTest {39protected DebugeeArgumentHandler argHandler;4041protected IOPipe pipe;4243protected Log log;4445protected boolean callExit = true;4647private boolean success = true;4849protected void setSuccess(boolean value) {50success = value;51}5253public boolean getSuccess() {54return success;55}5657public final static int DEFAULT_BREAKPOINT_LINE = 63;5859public final static String DEFAULT_BREAKPOINT_METHOD_NAME = "breakpointMethod";6061public void breakpointMethod() {62log.display("In breakpoint method: 'AbstractDebuggeeTest.breakpointMethod()'"); // DEFAULT_BREAKPOINT_LINE63}6465protected Map<String, ClassUnloader> loadedClasses = new TreeMap<String, ClassUnloader>();6667public final static String COMMAND_FORCE_BREAKPOINT = "forceBreakpoint";6869//load class with given name with possibility to unload it70static public final String COMMAND_LOAD_CLASS = "loadClass";7172// unload class with given name(it is possible for classes loaded via loadTestClass method)73// command:className[:<unloadResult>], <unloadResult> - one of UNLOAD_RESULT_TRUE or UNLOAD_RESULT_FALSE74static public final String COMMAND_UNLOAD_CLASS = "unloadClass";7576// Optional arguments of COMMAND_UNLOAD_CLASS77// (is after unloading class should be really unloaded, default value is UNLOAD_RESULT_TRUE)78static public final String UNLOAD_RESULT_TRUE = "unloadResultTrue";7980static public final String UNLOAD_RESULT_FALSE = "unloadResultFalse";8182static public final String COMMAND_CREATE_STATETESTTHREAD = "createStateTestThread";8384static public final String COMMAND_NEXTSTATE_STATETESTTHREAD = "stateTestThreadNextState";8586//force GC using AbstractDebuggeeTest.eatMemory()87static public final String COMMAND_FORCE_GC = "forceGC";88// GCcount is used to get information about GC activity during test89static public final String COMMAND_GC_COUNT = "GCcount";90private int lastGCCount;919293static public final String stateTestThreadName = "stateTestThread";9495static public final String stateTestThreadClassName = StateTestThread.class.getName();9697// path to classes intended for loading/unloading98protected String classpath;99100// classloader loads only test classes from nsk.*101public static class TestClassLoader extends CustomClassLoader {102public Class<?> loadClass(String name) throws ClassNotFoundException {103if (name.startsWith("nsk."))104return findClass(name);105else106return super.loadClass(name);107}108}109110protected StressOptions stressOptions;111protected Stresser stresser;112113// initialize test and remove unsupported by nsk.share.jdi.ArgumentHandler arguments114// (ArgumentHandler constructor throws BadOption exception if command line contains unrecognized by ArgumentHandler options)115// support -testClassPath parameter: path to find classes for custom classloader116protected String[] doInit(String[] args) {117stressOptions = new StressOptions(args);118stresser = new Stresser(stressOptions);119120ArrayList<String> standardArgs = new ArrayList<String>();121122for (int i = 0; i < args.length; i++) {123if (args[i].equals("-testClassPath") && (i < args.length - 1)) {124classpath = args[i + 1];125i++;126} else127standardArgs.add(args[i]);128}129130return standardArgs.toArray(new String[] {});131}132133public void loadTestClass(String className) {134if (classpath == null) {135throw new TestBug("Debuggee requires 'testClassPath' parameter");136}137138try {139ClassUnloader classUnloader = new ClassUnloader();140141classUnloader.setClassLoader(new TestClassLoader());142classUnloader.loadClass(className, classpath);143loadedClasses.put(className, classUnloader);144} catch (ClassNotFoundException e) {145log.complain("Unexpected 'ClassNotFoundException' on loading of the requested class(" + className + ")");146e.printStackTrace(log.getOutStream());147throw new TestBug("Unexpected 'ClassNotFoundException' on loading of the requested class(" + className + ")");148}149}150151public static final int MAX_UNLOAD_ATTEMPS = 5;152153public void unloadTestClass(String className, boolean expectedUnloadingResult) {154ClassUnloader classUnloader = loadedClasses.get(className);155156int unloadAttemps = 0;157158if (classUnloader != null) {159boolean wasUnloaded = false;160161while (!wasUnloaded && (unloadAttemps++ < MAX_UNLOAD_ATTEMPS)) {162wasUnloaded = classUnloader.unloadClass();163}164165if (wasUnloaded)166loadedClasses.remove(className);167else {168log.display("Class " + className + " was not unloaded");169}170171if (wasUnloaded != expectedUnloadingResult) {172setSuccess(false);173174if (wasUnloaded)175log.complain("Class " + className + " was unloaded!");176else177log.complain("Class " + className + " wasn't unloaded!");178}179} else {180log.complain("Invalid command 'unloadClass' is requested: class " + className + " was not loaded via ClassUnloader");181throw new TestBug("Invalid command 'unloadClass' is requested: class " + className + " was not loaded via ClassUnloader");182}183}184185static public void sleep1sec() {186try {187Thread.sleep(1000);188} catch (InterruptedException e) {189}190}191192private StateTestThread stateTestThread;193194public static final String COMMAND_QUIT = "quit";195196public static final String COMMAND_READY = "ready";197198private void createStateTestThread() {199if (stateTestThread != null)200throw new TestBug("StateTestThread already created");201202stateTestThread = new StateTestThread(stateTestThreadName);203}204205private void stateTestThreadNextState() {206if (stateTestThread == null)207throw new TestBug("StateTestThread not created");208209stateTestThread.nextState();210}211212public boolean parseCommand(String command) {213try {214StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(command));215tokenizer.whitespaceChars(':', ':');216tokenizer.wordChars('_', '_');217tokenizer.wordChars('$', '$');218tokenizer.wordChars('[', ']');219220if (command.equals(COMMAND_FORCE_GC)) {221forceGC();222lastGCCount = getCurrentGCCount();223return true;224} else if (command.equals(COMMAND_GC_COUNT)) {225pipe.println(COMMAND_GC_COUNT + ":" + (getCurrentGCCount() - lastGCCount));226return true;227} else if (command.equals(COMMAND_FORCE_BREAKPOINT)) {228breakpointMethod();229return true;230} else if (command.equals(COMMAND_CREATE_STATETESTTHREAD)) {231createStateTestThread();232233return true;234} else if (command.equals(COMMAND_NEXTSTATE_STATETESTTHREAD)) {235stateTestThreadNextState();236237return true;238} else if (command.startsWith(COMMAND_LOAD_CLASS)) {239tokenizer.nextToken();240241if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)242throw new TestBug("Invalid command format: " + command);243244String className = tokenizer.sval;245246loadTestClass(className);247248return true;249} else if (command.startsWith(COMMAND_UNLOAD_CLASS)) {250tokenizer.nextToken();251252if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)253throw new TestBug("Invalid command format: " + command);254255String className = tokenizer.sval;256257boolean expectedUnloadingResult = true;258259if (tokenizer.nextToken() == StreamTokenizer.TT_WORD) {260if (tokenizer.sval.equals(UNLOAD_RESULT_TRUE))261expectedUnloadingResult = true;262else if (tokenizer.sval.equals(UNLOAD_RESULT_FALSE))263expectedUnloadingResult = false;264else265throw new TestBug("Invalid command format: " + command);266}267268unloadTestClass(className, expectedUnloadingResult);269270return true;271}272} catch (IOException e) {273throw new TestBug("Invalid command format: " + command);274}275276return false;277}278279protected DebugeeArgumentHandler createArgumentHandler(String args[]) {280return new DebugeeArgumentHandler(args);281}282283protected void init(String args[]) {284argHandler = createArgumentHandler(doInit(args));285pipe = argHandler.createDebugeeIOPipe();286log = argHandler.createDebugeeLog();287lastGCCount = getCurrentGCCount();288}289290public void initDebuggee(DebugeeArgumentHandler argHandler, Log log, IOPipe pipe, String[] args, boolean callExit) {291this.argHandler = argHandler;292this.log = log;293this.pipe = pipe;294this.callExit = callExit;295doInit(args);296}297298public void doTest(String args[]) {299init(args);300doTest();301}302303public void doTest() {304do {305log.display("Debuggee " + getClass().getName() + " : sending the command: " + AbstractDebuggeeTest.COMMAND_READY);306pipe.println(AbstractDebuggeeTest.COMMAND_READY);307308String command = pipe.readln();309log.display("Debuggee: received the command: " + command);310311if (command.equals(AbstractDebuggeeTest.COMMAND_QUIT)) {312break;313} else {314try {315if (!parseCommand(command)) {316log.complain("TEST BUG: unknown debugger command: " + command);317System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);318}319} catch (Throwable t) {320log.complain("Unexpected exception in debuggee: " + t);321t.printStackTrace(log.getOutStream());322System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);323}324}325} while (true);326327log.display("Debuggee: exiting");328329if (callExit) {330if (success)331System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_PASSED);332else333System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);334}335}336337public static void eatMemory() {338Runtime runtime = Runtime.getRuntime();339long maxMemory = runtime.maxMemory();340int memoryChunk = (int) (maxMemory / 50);341try {342List<Object> list = new ArrayList<Object>();343while (true) {344list.add(new byte[memoryChunk]);345}346} catch (OutOfMemoryError e) {347// expected exception348}349}350351public static int getCurrentGCCount() {352int result = 0;353List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();354for (GarbageCollectorMXBean bean : gcBeans) {355result += bean.getCollectionCount();356}357return result;358}359360public void forceGC() {361eatMemory();362}363364public void voidValueMethod() {365}366367public void unexpectedException(Throwable t) {368setSuccess(false);369t.printStackTrace(log.getOutStream());370log.complain("Unexpected exception: " + t);371}372373}374375376