1 /* 2 * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package nsk.share.jdi; 24 25 import java.io.*; 26 import java.util.*; 27 import nsk.share.Log; 28 import nsk.share.ObjectInstancesManager; 29 import nsk.share.TestBug; 30 import nsk.share.jpda.DebugeeArgumentHandler; 31 import nsk.share.jpda.IOPipe; 32 33 /* 34 * Debuggee class used in tests for heapwalking(tests for VirtualMachine.instanceCounts, ReferenceType.instances, ObjectReference.referrers). 35 * Handle commands related to creation of objects instances with given reference type 36 * and given referrers number, use for this purposes nsk.share.ObjectInstancesManager. 37 */ 38 public class HeapwalkingDebuggee extends AbstractJDIDebuggee { 39 protected ObjectInstancesManager objectInstancesManager; 40 41 // reference of this type should be included in ObjectReference.referringObjects 42 public static Set<String> includedIntoReferrersCountTypes = new HashSet<String>(); 43 44 // reference of this type should be included in ReferenceType.instances 45 public static Set<String> includedIntoInstancesCountTypes = new HashSet<String>(); 46 47 static { 48 includedIntoInstancesCountTypes.add(ObjectInstancesManager.STRONG_REFERENCE); 49 includedIntoInstancesCountTypes.add(ObjectInstancesManager.WEAK_REFERENCE); 50 includedIntoInstancesCountTypes.add(ObjectInstancesManager.SOFT_REFERENCE); 51 includedIntoInstancesCountTypes.add(ObjectInstancesManager.PHANTOM_REFERENCE); 52 includedIntoInstancesCountTypes.add(ObjectInstancesManager.JNI_GLOBAL_REFERENCE); 53 includedIntoInstancesCountTypes.add(ObjectInstancesManager.JNI_LOCAL_REFERENCE); 54 55 includedIntoReferrersCountTypes.add(ObjectInstancesManager.STRONG_REFERENCE); 56 includedIntoReferrersCountTypes.add(ObjectInstancesManager.WEAK_REFERENCE); 57 includedIntoReferrersCountTypes.add(ObjectInstancesManager.SOFT_REFERENCE); 58 includedIntoReferrersCountTypes.add(ObjectInstancesManager.PHANTOM_REFERENCE); 59 } 60 61 //create number instance of class with given name, command format: createInstances:class_name:instance_count[:referrer_count:referrer_type] 62 static public final String COMMAND_CREATE_INSTANCES = "createInstances"; 63 64 //'delete'(make unreachable) number instance of class with given name, command format: deleteInstances:class_name:instance_count:referrer_count 65 static public final String COMMAND_DELETE_INSTANCES = "deleteInstances"; 66 67 //delete number referrers 68 static public final String COMMAND_DELETE_REFERRERS = "deleteReferrers"; 69 70 //create instance with all type referrers 71 static public final String COMMAND_CREATE_ALL_TYPE_REFERENCES = "createAllTypeReferences"; 72 73 protected void init(String args[]) { 74 super.init(args); 75 objectInstancesManager = new ObjectInstancesManager(log); 76 } 77 78 public void initDebuggee(DebugeeArgumentHandler argHandler, Log log, IOPipe pipe, String args[], boolean callExit) { 79 super.initDebuggee(argHandler, log, pipe, args, callExit); 80 objectInstancesManager = new ObjectInstancesManager(log); 81 } 82 83 public boolean parseCommand(String command) { 84 if (super.parseCommand(command)) 85 return true; 86 87 try { 88 StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(command)); 89 tokenizer.whitespaceChars(':', ':'); 90 tokenizer.wordChars('_', '_'); 91 tokenizer.wordChars('$', '$'); 92 tokenizer.wordChars('[', ']'); 93 tokenizer.wordChars('|', '|'); 94 95 if (command.startsWith(COMMAND_CREATE_INSTANCES)) { 96 //createInstances:class_name:instance_count[:referrer_count:referrer_type] 97 98 tokenizer.nextToken(); 99 100 if (tokenizer.nextToken() != StreamTokenizer.TT_WORD) 101 throw new TestBug("Invalid command format: " + command); 102 103 String className = tokenizer.sval; 104 105 if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER) 106 throw new TestBug("Invalid command format: " + command); 107 108 int instanceCounts = (int) tokenizer.nval; 109 110 int referrerCount = 1; 111 Set<String> referrerType = new HashSet<String>(); 112 113 if (tokenizer.nextToken() == StreamTokenizer.TT_NUMBER) { 114 referrerCount = (int) tokenizer.nval; 115 116 if (tokenizer.nextToken() == StreamTokenizer.TT_WORD) 117 referrerType.addAll(Arrays.asList(tokenizer.sval.split("\\|"))); 118 } 119 if (referrerType.isEmpty()) { 120 referrerType.add(ObjectInstancesManager.STRONG_REFERENCE); 121 } 122 123 objectInstancesManager.createReferences(instanceCounts, className, referrerCount, referrerType); 124 125 return true; 126 } else if (command.startsWith(COMMAND_DELETE_INSTANCES)) { 127 //deleteInstances:class_name:instance_count:referrer_count 128 129 tokenizer.nextToken(); 130 131 if (tokenizer.nextToken() != StreamTokenizer.TT_WORD) 132 throw new TestBug("Invalid command format: " + command); 133 134 String className = tokenizer.sval; 135 136 if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER) 137 throw new TestBug("Invalid command format: " + command); 138 139 int instanceCounts = (int) tokenizer.nval; 140 141 objectInstancesManager.deleteAllReferrers(instanceCounts, className); 142 143 return true; 144 } else if (command.startsWith(COMMAND_DELETE_REFERRERS)) { 145 tokenizer.nextToken(); 146 147 if (tokenizer.nextToken() != StreamTokenizer.TT_WORD) 148 throw new TestBug("Invalid command format: " + command); 149 150 String className = tokenizer.sval; 151 152 if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER) 153 throw new TestBug("Invalid command format: " + command); 154 155 int referrersCount = (int) tokenizer.nval; 156 157 Set<String> referrerTypes = new HashSet<String>(); 158 if (tokenizer.nextToken() == StreamTokenizer.TT_WORD) { 159 referrerTypes.addAll(Arrays.asList(tokenizer.sval.split("\\|"))); 160 } 161 162 objectInstancesManager.deleteReferrers(className, referrersCount, referrerTypes); 163 164 return true; 165 } else if (command.startsWith(COMMAND_CREATE_ALL_TYPE_REFERENCES)) { 166 tokenizer.nextToken(); 167 168 if (tokenizer.nextToken() != StreamTokenizer.TT_WORD) 169 throw new TestBug("Invalid command format: " + command); 170 171 String className = tokenizer.sval; 172 173 if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER) 174 throw new TestBug("Invalid command format: " + command); 175 176 int instanceCounts = (int) tokenizer.nval; 177 178 objectInstancesManager.createAllTypeReferences(className, instanceCounts); 179 180 return true; 181 } 182 } catch (IOException e) { 183 throw new TestBug("Invalid command format: " + command); 184 } 185 186 return false; 187 } 188 189 // instances of some classes couldn't be strictly controlled during test execution, use non-strict checks for this classes 190 public static boolean useStrictCheck(String className, boolean otherThreadPresent) { 191 if (className.equals("java.lang.String")) 192 return false; 193 194 if (className.equals("char[]")) 195 return false; 196 197 if (className.equals("byte[]")) 198 return false; 199 200 if (className.equals("boolean[]")) 201 return false; 202 203 if (className.equals("float[]")) 204 return false; 205 206 if (className.equals("long[]")) 207 return false; 208 209 if (className.equals("int[]")) 210 return false; 211 212 if (className.equals("double[]")) 213 return false; 214 215 if (className.equals("java.lang.Thread")) { 216 if (otherThreadPresent) 217 return false; 218 } 219 220 return true; 221 } 222 223 // is reference with given type should be included in ObjectReference.referringObjects 224 static public boolean isIncludedIntoReferrersCount(String referenceType) { 225 if (!ObjectInstancesManager.allReferenceTypes.contains(referenceType)) { 226 throw new TestBug("Invalid reference type: " + referenceType); 227 } 228 229 return includedIntoReferrersCountTypes.contains(referenceType); 230 } 231 232 // is reference with given type should be included in ReferenceType.instances 233 static public boolean isIncludedIntoInstancesCount(String referenceType) { 234 if (!ObjectInstancesManager.allReferenceTypes.contains(referenceType)) { 235 throw new TestBug("Invalid reference type: " + referenceType); 236 } 237 238 return includedIntoInstancesCountTypes.contains(referenceType); 239 } 240 241 public static void main(String args[]) { 242 HeapwalkingDebuggee debuggee = new HeapwalkingDebuggee(); 243 debuggee.init(args); 244 debuggee.doTest(); 245 } 246 }