| /* |
| * Copyright (c) 2006, 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.jdi; |
| |
| import java.io.*; |
| import java.util.*; |
| import nsk.share.Log; |
| import nsk.share.ObjectInstancesManager; |
| import nsk.share.TestBug; |
| import nsk.share.jpda.DebugeeArgumentHandler; |
| import nsk.share.jpda.IOPipe; |
| |
| /* |
| * Debuggee class used in tests for heapwalking(tests for VirtualMachine.instanceCounts, ReferenceType.instances, ObjectReference.referrers). |
| * Handle commands related to creation of objects instances with given reference type |
| * and given referrers number, use for this purposes nsk.share.ObjectInstancesManager. |
| */ |
| public class HeapwalkingDebuggee extends AbstractJDIDebuggee { |
| protected ObjectInstancesManager objectInstancesManager; |
| |
| // reference of this type should be included in ObjectReference.referringObjects |
| public static Set<String> includedIntoReferrersCountTypes = new HashSet<String>(); |
| |
| // reference of this type should be included in ReferenceType.instances |
| public static Set<String> includedIntoInstancesCountTypes = new HashSet<String>(); |
| |
| static { |
| includedIntoInstancesCountTypes.add(ObjectInstancesManager.STRONG_REFERENCE); |
| includedIntoInstancesCountTypes.add(ObjectInstancesManager.WEAK_REFERENCE); |
| includedIntoInstancesCountTypes.add(ObjectInstancesManager.SOFT_REFERENCE); |
| includedIntoInstancesCountTypes.add(ObjectInstancesManager.PHANTOM_REFERENCE); |
| includedIntoInstancesCountTypes.add(ObjectInstancesManager.JNI_GLOBAL_REFERENCE); |
| includedIntoInstancesCountTypes.add(ObjectInstancesManager.JNI_LOCAL_REFERENCE); |
| |
| includedIntoReferrersCountTypes.add(ObjectInstancesManager.STRONG_REFERENCE); |
| includedIntoReferrersCountTypes.add(ObjectInstancesManager.WEAK_REFERENCE); |
| includedIntoReferrersCountTypes.add(ObjectInstancesManager.SOFT_REFERENCE); |
| includedIntoReferrersCountTypes.add(ObjectInstancesManager.PHANTOM_REFERENCE); |
| } |
| |
| //create number instance of class with given name, command format: createInstances:class_name:instance_count[:referrer_count:referrer_type] |
| static public final String COMMAND_CREATE_INSTANCES = "createInstances"; |
| |
| //'delete'(make unreachable) number instance of class with given name, command format: deleteInstances:class_name:instance_count:referrer_count |
| static public final String COMMAND_DELETE_INSTANCES = "deleteInstances"; |
| |
| //delete number referrers |
| static public final String COMMAND_DELETE_REFERRERS = "deleteReferrers"; |
| |
| //create instance with all type referrers |
| static public final String COMMAND_CREATE_ALL_TYPE_REFERENCES = "createAllTypeReferences"; |
| |
| protected void init(String args[]) { |
| super.init(args); |
| objectInstancesManager = new ObjectInstancesManager(log); |
| } |
| |
| public void initDebuggee(DebugeeArgumentHandler argHandler, Log log, IOPipe pipe, String args[], boolean callExit) { |
| super.initDebuggee(argHandler, log, pipe, args, callExit); |
| objectInstancesManager = new ObjectInstancesManager(log); |
| } |
| |
| public boolean parseCommand(String command) { |
| if (super.parseCommand(command)) |
| return true; |
| |
| try { |
| StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(command)); |
| tokenizer.whitespaceChars(':', ':'); |
| tokenizer.wordChars('_', '_'); |
| tokenizer.wordChars('$', '$'); |
| tokenizer.wordChars('[', ']'); |
| tokenizer.wordChars('|', '|'); |
| |
| if (command.startsWith(COMMAND_CREATE_INSTANCES)) { |
| //createInstances:class_name:instance_count[:referrer_count:referrer_type] |
| |
| tokenizer.nextToken(); |
| |
| if (tokenizer.nextToken() != StreamTokenizer.TT_WORD) |
| throw new TestBug("Invalid command format: " + command); |
| |
| String className = tokenizer.sval; |
| |
| if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER) |
| throw new TestBug("Invalid command format: " + command); |
| |
| int instanceCounts = (int) tokenizer.nval; |
| |
| int referrerCount = 1; |
| Set<String> referrerType = new HashSet<String>(); |
| |
| if (tokenizer.nextToken() == StreamTokenizer.TT_NUMBER) { |
| referrerCount = (int) tokenizer.nval; |
| |
| if (tokenizer.nextToken() == StreamTokenizer.TT_WORD) |
| referrerType.addAll(Arrays.asList(tokenizer.sval.split("\\|"))); |
| } |
| if (referrerType.isEmpty()) { |
| referrerType.add(ObjectInstancesManager.STRONG_REFERENCE); |
| } |
| |
| objectInstancesManager.createReferences(instanceCounts, className, referrerCount, referrerType); |
| |
| return true; |
| } else if (command.startsWith(COMMAND_DELETE_INSTANCES)) { |
| //deleteInstances:class_name:instance_count:referrer_count |
| |
| tokenizer.nextToken(); |
| |
| if (tokenizer.nextToken() != StreamTokenizer.TT_WORD) |
| throw new TestBug("Invalid command format: " + command); |
| |
| String className = tokenizer.sval; |
| |
| if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER) |
| throw new TestBug("Invalid command format: " + command); |
| |
| int instanceCounts = (int) tokenizer.nval; |
| |
| objectInstancesManager.deleteAllReferrers(instanceCounts, className); |
| |
| return true; |
| } else if (command.startsWith(COMMAND_DELETE_REFERRERS)) { |
| tokenizer.nextToken(); |
| |
| if (tokenizer.nextToken() != StreamTokenizer.TT_WORD) |
| throw new TestBug("Invalid command format: " + command); |
| |
| String className = tokenizer.sval; |
| |
| if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER) |
| throw new TestBug("Invalid command format: " + command); |
| |
| int referrersCount = (int) tokenizer.nval; |
| |
| Set<String> referrerTypes = new HashSet<String>(); |
| if (tokenizer.nextToken() == StreamTokenizer.TT_WORD) { |
| referrerTypes.addAll(Arrays.asList(tokenizer.sval.split("\\|"))); |
| } |
| |
| objectInstancesManager.deleteReferrers(className, referrersCount, referrerTypes); |
| |
| return true; |
| } else if (command.startsWith(COMMAND_CREATE_ALL_TYPE_REFERENCES)) { |
| tokenizer.nextToken(); |
| |
| if (tokenizer.nextToken() != StreamTokenizer.TT_WORD) |
| throw new TestBug("Invalid command format: " + command); |
| |
| String className = tokenizer.sval; |
| |
| if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER) |
| throw new TestBug("Invalid command format: " + command); |
| |
| int instanceCounts = (int) tokenizer.nval; |
| |
| objectInstancesManager.createAllTypeReferences(className, instanceCounts); |
| |
| return true; |
| } |
| } catch (IOException e) { |
| throw new TestBug("Invalid command format: " + command); |
| } |
| |
| return false; |
| } |
| |
| // instances of some classes couldn't be strictly controlled during test execution, use non-strict checks for this classes |
| public static boolean useStrictCheck(String className, boolean otherThreadPresent) { |
| if (className.equals("java.lang.String")) |
| return false; |
| |
| if (className.equals("char[]")) |
| return false; |
| |
| if (className.equals("byte[]")) |
| return false; |
| |
| if (className.equals("java.lang.Thread")) { |
| if (otherThreadPresent) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| // is reference with given type should be included in ObjectReference.referringObjects |
| static public boolean isIncludedIntoReferrersCount(String referenceType) { |
| if (!ObjectInstancesManager.allReferenceTypes.contains(referenceType)) { |
| throw new TestBug("Invalid reference type: " + referenceType); |
| } |
| |
| return includedIntoReferrersCountTypes.contains(referenceType); |
| } |
| |
| // is reference with given type should be included in ReferenceType.instances |
| static public boolean isIncludedIntoInstancesCount(String referenceType) { |
| if (!ObjectInstancesManager.allReferenceTypes.contains(referenceType)) { |
| throw new TestBug("Invalid reference type: " + referenceType); |
| } |
| |
| return includedIntoInstancesCountTypes.contains(referenceType); |
| } |
| |
| public static void main(String args[]) { |
| HeapwalkingDebuggee debuggee = new HeapwalkingDebuggee(); |
| debuggee.init(args); |
| debuggee.doTest(); |
| } |
| } |