1 /* 2 * Copyright (c) 2002, 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.jdi.Method.isObsolete; 24 25 import nsk.share.*; 26 import nsk.share.jpda.*; 27 import nsk.share.jdi.*; 28 29 import com.sun.jdi.*; 30 import com.sun.jdi.connect.*; 31 import com.sun.jdi.request.*; 32 import com.sun.jdi.event.*; 33 import java.io.*; 34 import java.util.*; 35 36 /** 37 */ 38 public class isobsolete003 { 39 40 private final static String prefix = "nsk.jdi.Method.isObsolete"; 41 private final static String className = ".isobsolete003"; 42 private final static String debuggerName = prefix + className; 43 private final static String debuggeeName = debuggerName + "a"; 44 private final static int brkpMainLineNumber = 48; 45 private final static int brkpFooLineNumber = 33; 46 47 private static int waitTime; 48 private static int exitStatus; 49 private static ArgumentHandler argHandler; 50 private static Log log; 51 private static Debugee debuggee; 52 private static VirtualMachine vm; 53 private static ReferenceType debuggeeClass; 54 55 private static EventRequestManager eventRManager; 56 private static EventSet eventSet; 57 private static EventIterator eventIterator; 58 main(String argv[])59 public static void main(String argv[]) { 60 System.exit(Consts.JCK_STATUS_BASE + run(argv, System.out)); 61 } 62 run(String argv[], PrintStream out)63 public static int run(String argv[], PrintStream out) { 64 65 exitStatus = Consts.TEST_PASSED; 66 67 argHandler = new ArgumentHandler(argv); 68 log = new Log(out, argHandler); 69 waitTime = argHandler.getWaitTime() * 60000; 70 71 try { 72 73 Binder binder = new Binder(argHandler, log); 74 debuggee = binder.bindToDebugee(debuggeeName); 75 debuggee.redirectStderr(log, "debuggee > "); 76 debuggee.createIOPipe(); 77 eventRManager = debuggee.getEventRequestManager(); 78 79 vm = debuggee.VM(); 80 eventRManager = vm.eventRequestManager(); 81 82 waitForDebuggeeClassPrepared(); 83 84 if (vm.canRedefineClasses()) { 85 86 execTest(); 87 88 debuggee.resume(); 89 getEventSet(); 90 if (eventIterator.nextEvent() instanceof VMDeathEvent) { 91 display("Waiting for the debuggee's finish..."); 92 debuggee.waitFor(); 93 94 display("Getting the debuggee's exit status."); 95 int status = debuggee.getStatus(); 96 if (status != (Consts.TEST_PASSED + Consts.JCK_STATUS_BASE)) { 97 complain("Debuggee returned UNEXPECTED exit status: " + status); 98 exitStatus = Consts.TEST_FAILED; 99 } 100 } else { 101 throw new TestBug("Last event is not the VMDeathEvent"); 102 } 103 104 } else { 105 display("vm.canRedefineClasses() == false : test is cancelled"); 106 vm.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); 107 } 108 109 } catch (VMDisconnectedException e) { 110 exitStatus = Consts.TEST_FAILED; 111 complain("The test cancelled due to VMDisconnectedException."); 112 e.printStackTrace(out); 113 display("Trying: vm.process().destroy();"); 114 if (vm != null) { 115 Process vmProcess = vm.process(); 116 if (vmProcess != null) { 117 vmProcess.destroy(); 118 } 119 } 120 121 } catch (Exception e) { 122 exitStatus = Consts.TEST_FAILED; 123 complain("Unexpected Exception: " + e.getMessage()); 124 e.printStackTrace(out); 125 complain("The test has not finished normally. Forcing: vm.exit()."); 126 if (vm != null) { 127 vm.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE); 128 } 129 debuggee.resume(); 130 getEventSet(); 131 } 132 133 return exitStatus; 134 } 135 136 execTest()137 private static void execTest() { 138 139 ThreadReference mainThread = debuggee.threadByName("main"); 140 141 // Set first breakpoint to have isobsolete003b class loaded. 142 BreakpointRequest bpRequest = debuggee.makeBreakpoint(debuggeeClass, "main", brkpMainLineNumber); 143 bpRequest.addThreadFilter(mainThread); 144 bpRequest.addCountFilter(1); 145 bpRequest.enable(); 146 147 waitForEvent(bpRequest); 148 bpRequest.disable(); 149 150 // At this point isobsolete003b class should be loaded in debuggee. 151 String redefName = prefix + ".isobsolete003b"; 152 153 ReferenceType redefClass = debuggee.classByName(redefName); 154 if (redefClass == null) { 155 throw new TestBug(redefName + "is not found in debuggee."); 156 } 157 158 String methodName = "foo"; 159 Method method = (Method) redefClass.methodsByName(methodName).get(0); 160 161 // save some values for check in future 162 Method oldMethod = method; 163 Location oldLocation = method.location(); 164 long oldCodeIndex = oldLocation.codeIndex(); 165 String oldRetTypeName = method.returnTypeName(); 166 int oldHashCode = method.hashCode(); 167 168 // Set new breakpoint to have isobsolete003b.foo() method on stack before redefinition. 169 bpRequest = debuggee.makeBreakpoint(redefClass, methodName, brkpFooLineNumber); 170 bpRequest.addThreadFilter(mainThread); 171 bpRequest.addCountFilter(1); 172 bpRequest.enable(); 173 174 waitForEvent(bpRequest); 175 bpRequest.disable(); 176 177 display("requested BreakpointEvent for foo() method received;"); 178 try { 179 if (!mainThread.frame(0).location().method().equals(method)) { 180 throw new TestBug("foo() method is not on the top of the main thread stack"); 181 } 182 } catch (IncompatibleThreadStateException e) { 183 throw new Failure("Unexpected IncompatibleThreadStateException while comparing mainThread.frame(0).location().method(): " + e.getMessage()); 184 } 185 186 display("Making redefineClasses(mapClassToBytes())."); 187 vm.redefineClasses(mapClassToBytes()); 188 189 // Check isObsolete after redefinition 190 try { 191 method = mainThread.frame(0).location().method(); 192 } catch (IncompatibleThreadStateException e) { 193 throw new Failure("Unexpected IncompatibleThreadStateException while getting mainThread.frame(0).location().method(): " + e.getMessage()); 194 } 195 if (!method.isObsolete()) { 196 complain("method.isObsolete() == true for foo() method after redefineClasses()"); 197 exitStatus = Consts.TEST_FAILED; 198 } else { 199 // Do other checks for obsolete method. 200 201 if (method.equals(oldMethod)) { 202 complain("equals(oldMethod) returned true for obsolete method."); 203 exitStatus = Consts.TEST_FAILED; 204 } 205 206 List l = null; 207 Location loc = null; 208 try { 209 l = method.allLineLocations(); 210 if (l.size() > 0) { 211 complain("allLineLocations() returned a list with non-zero size for obsolete method." + 212 "Number of Locations :" + l.size()); 213 exitStatus = Consts.TEST_FAILED; 214 } 215 } catch (AbsentInformationException e) { 216 // it is expected 217 } 218 219 try { 220 l = method.allLineLocations(vm.getDefaultStratum(), null); 221 if (l.size() > 0) { 222 complain("allLineLocations(vm.getDefaultStratum(), null) returned a list with non-zero size for obsolete method." + 223 "Number of Locations :" + l.size()); 224 exitStatus = Consts.TEST_FAILED; 225 } 226 } catch (AbsentInformationException e) { 227 // it is expected 228 } 229 230 try { 231 l = method.locationsOfLine(1); 232 if (l.size() > 0) { 233 complain("locationsOfLine(1) returned a list with non-zero size for obsolete method." + 234 "Number of Locations :" + l.size()); 235 exitStatus = Consts.TEST_FAILED; 236 } 237 } catch (AbsentInformationException e) { 238 // it is expected 239 } 240 241 try { 242 l = method.locationsOfLine(vm.getDefaultStratum(), null, 1); 243 if (l.size() > 0) { 244 complain("locationsOfLine(vm.getDefaultStratum(), null, 1) returned a list with non-zero size for obsolete method." + 245 "Number of Locations :" + l.size()); 246 exitStatus = Consts.TEST_FAILED; 247 } 248 } catch (AbsentInformationException e) { 249 // it is expected 250 } 251 252 try { 253 l = method.arguments(); 254 if (l.size() > 0) { 255 complain("arguments() returned a list with non-zero size for obsolete method." + 256 "Size of list :" + l.size()); 257 exitStatus = Consts.TEST_FAILED; 258 } 259 } catch (AbsentInformationException e) { 260 // it is expected 261 } 262 263 l = method.argumentTypeNames(); 264 if (l.size() > 0) { 265 complain("argumentTypeNames() returned a list with non-zero size for obsolete method." + 266 "Size of list :" + l.size()); 267 exitStatus = Consts.TEST_FAILED; 268 } 269 270 try { 271 l = method.argumentTypes(); 272 if (l.size() > 0) { 273 complain("argumentsTypes() returned a list with non-zero size for obsolete method." + 274 "Size of list :" + l.size()); 275 exitStatus = Consts.TEST_FAILED; 276 } 277 } catch (ClassNotLoadedException e) { 278 // it is expected 279 } 280 281 try { 282 l = method.variables(); 283 if (l.size() > 0) { 284 complain("variables() returned a list with non-zero size for obsolete method." + 285 "Size of list :" + l.size()); 286 exitStatus = Consts.TEST_FAILED; 287 } 288 } catch (AbsentInformationException e) { 289 // it is expected 290 } 291 292 try { 293 l = method.variablesByName("dummyInt"); 294 if (l.size() > 0) { 295 complain("variablesByName(oldVar.name()) returned a list with non-zero size for obsolete method." + 296 "Size of list :" + l.size()); 297 exitStatus = Consts.TEST_FAILED; 298 } 299 } catch (AbsentInformationException e) { 300 // it is expected 301 } 302 303 byte[] b = method.bytecodes(); 304 if (b.length > 0) { 305 complain("bytecodes() returned an array with non-zero length for obsolete method." + 306 "Number of bytes :" + b.length); 307 exitStatus = Consts.TEST_FAILED; 308 } 309 310 loc = method.location(); 311 if (loc != null && loc == oldLocation) { 312 complain("location() returned old location for obsolete method."); 313 exitStatus = Consts.TEST_FAILED; 314 } 315 316 loc = method.locationOfCodeIndex(oldCodeIndex); 317 if (loc != null) { 318 complain("locationOfCodeIndex(oldCodeIndex) returned not-null location for obsolete method."); 319 exitStatus = Consts.TEST_FAILED; 320 } 321 322 String rtName = method.returnTypeName(); 323 if (rtName.equals(oldRetTypeName)) { 324 complain("returnTypeName() returned an old string for obsolete method: " + rtName); 325 exitStatus = Consts.TEST_FAILED; 326 } 327 328 try { 329 Type rType = method.returnType(); 330 if (rType != null) { 331 complain("returnType() returned not-null Type for obsolete method: " + rType.name()); 332 exitStatus = Consts.TEST_FAILED; 333 } 334 } catch (ClassNotLoadedException e) { 335 // it is expected 336 } 337 338 int hashCode = method.hashCode(); 339 if (hashCode == oldHashCode) { 340 complain("hashCode() returned old value for obsolete method: " + hashCode); 341 exitStatus = Consts.TEST_FAILED; 342 } 343 } 344 } 345 display(String msg)346 private static void display(String msg) { 347 log.display("debugger > " + msg); 348 } 349 complain(String msg)350 private static void complain(String msg) { 351 log.complain("debugger FAILURE > " + msg); 352 } 353 354 /** 355 * Returns Map object for redefinition. 356 * 357 */ mapClassToBytes()358 private static Map<? extends com.sun.jdi.ReferenceType,byte[]> mapClassToBytes() { 359 String[] args = argHandler.getArguments(); 360 if (args.length <= 0) { 361 throw new Failure("mapClassToBytes(): Test arguments are not found."); 362 } 363 364 String testDir = args[0]; 365 display("Test current dir = " + testDir); 366 367 String filePrefix = File.separator + "nsk" 368 + File.separator + "jdi" 369 + File.separator + "Method" 370 + File.separator + "isObsolete"; 371 372 String fileToRedefineName = testDir + 373 File.separator + "newclass" + filePrefix 374 + File.separator + "isobsolete003b.class"; 375 376 display("fileToRedefineName : " + fileToRedefineName); 377 378 byte[] arrayToRedefine; 379 try { 380 File fileToRedefine = new File(fileToRedefineName); 381 if (!fileToRedefine.exists()) { 382 throw new Failure("mapClassToBytes(): fileToRedefine does not exist"); 383 } 384 385 FileInputStream inputFile = new FileInputStream(fileToRedefine); 386 arrayToRedefine = new byte [(int) fileToRedefine.length()]; 387 inputFile.read(arrayToRedefine); 388 inputFile.close(); 389 390 } catch (IOException e) { 391 complain("unexpected IOException: " + e); 392 throw new Failure(e); 393 } 394 395 String testClassName = prefix + ".isobsolete003b"; 396 ReferenceType testClass = debuggee.classByName(testClassName); 397 398 HashMap<com.sun.jdi.ReferenceType,byte[]> mapForClass = new HashMap<com.sun.jdi.ReferenceType,byte[]>(); 399 mapForClass.put(testClass, arrayToRedefine); 400 401 return mapForClass; 402 } 403 waitForEvent(EventRequest evRequest)404 private static Event waitForEvent (EventRequest evRequest) { 405 406 vm.resume(); 407 Event resultEvent = null; 408 try { 409 eventSet = null; 410 eventIterator = null; 411 eventSet = vm.eventQueue().remove(waitTime); 412 if (eventSet == null) { 413 throw new Failure("TIMEOUT while waiting for an event"); 414 } 415 eventIterator = eventSet.eventIterator(); 416 while (eventIterator.hasNext()) { 417 Event curEvent = eventIterator.nextEvent(); 418 if (curEvent instanceof VMDisconnectEvent) { 419 throw new Failure("Unexpected VMDisconnectEvent received."); 420 } else if (curEvent.request().equals(evRequest)) { 421 display("Requested event received."); 422 resultEvent = curEvent; 423 break; 424 } else { 425 throw new TestBug("Unexpected Event received: " + curEvent.toString()); 426 } 427 } 428 } catch (Exception e) { 429 throw new Failure("Unexpected exception while waiting for an event: " + e); 430 } 431 return resultEvent; 432 } 433 getEventSet()434 private static void getEventSet() { 435 try { 436 eventSet = vm.eventQueue().remove(waitTime); 437 if (eventSet == null) { 438 throw new Failure("TIMEOUT while waiting for an event"); 439 } 440 eventIterator = eventSet.eventIterator(); 441 } catch (Exception e) { 442 throw new Failure("getEventSet(): Unexpected exception while waiting for an event: " + e); 443 } 444 } 445 waitForDebuggeeClassPrepared()446 private static void waitForDebuggeeClassPrepared () { 447 display("Creating request for ClassPrepareEvent for debuggee."); 448 ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest(); 449 cpRequest.addClassFilter(debuggeeName); 450 cpRequest.addCountFilter(1); 451 cpRequest.enable(); 452 453 ClassPrepareEvent event = (ClassPrepareEvent) waitForEvent(cpRequest); 454 cpRequest.disable(); 455 456 debuggeeClass = event.referenceType(); 457 if (!debuggeeClass.name().equals(debuggeeName)) 458 throw new Failure("Unexpected class name for ClassPrepareEvent : " + debuggeeClass.name()); 459 } 460 } 461