1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 /** 20 * @author Vitaly A. Provodin 21 */ 22 23 package org.apache.harmony.jpda.tests.framework.jdwp; 24 25 import java.io.IOException; 26 import java.util.ArrayList; 27 import java.util.Iterator; 28 import java.util.List; 29 30 import org.apache.harmony.jpda.tests.framework.Breakpoint; 31 import org.apache.harmony.jpda.tests.framework.LogWriter; 32 import org.apache.harmony.jpda.tests.framework.TestErrorException; 33 import org.apache.harmony.jpda.tests.framework.TestOptions; 34 import org.apache.harmony.jpda.tests.framework.jdwp.Capabilities; 35 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket; 36 import org.apache.harmony.jpda.tests.framework.jdwp.Event; 37 import org.apache.harmony.jpda.tests.framework.jdwp.EventMod; 38 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants; 39 import org.apache.harmony.jpda.tests.framework.jdwp.Location; 40 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket; 41 import org.apache.harmony.jpda.tests.framework.jdwp.TransportWrapper; 42 import org.apache.harmony.jpda.tests.framework.jdwp.TypesLengths; 43 import org.apache.harmony.jpda.tests.framework.jdwp.Frame.Variable; 44 import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.ReplyErrorCodeException; 45 import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.TimeoutException; 46 47 /** 48 * This class provides convenient way for communicating with debuggee VM using 49 * JDWP packets. 50 * <p> 51 * Most methods can throw ReplyErrorCodeException if error occurred in execution 52 * of corresponding JDWP command or TestErrorException if any other error 53 * occurred. 54 */ 55 public class VmMirror { 56 57 /** Target VM Capabilities. */ 58 public Capabilities targetVMCapabilities; 59 60 /** Transport used to sent and receive packets. */ 61 private TransportWrapper connection; 62 63 /** PacketDispatcher thread used for asynchronous reading packets. */ 64 private PacketDispatcher packetDispatcher; 65 66 /** Test run options. */ 67 protected TestOptions config; 68 69 /** Log to write messages. */ 70 protected LogWriter logWriter; 71 72 /** 73 * Creates new VmMirror instance for given test run options. 74 * 75 * @param config 76 * test run options 77 * @param logWriter 78 * log writer 79 */ VmMirror(TestOptions config, LogWriter logWriter)80 public VmMirror(TestOptions config, LogWriter logWriter) { 81 connection = null; 82 this.config = config; 83 this.logWriter = logWriter; 84 } 85 86 /** 87 * Checks error code of given reply packet and throws 88 * ReplyErrorCodeException if any error detected. 89 * 90 * @param reply 91 * reply packet to check 92 * @return ReplyPacket unchanged reply packet 93 */ checkReply(ReplyPacket reply)94 public ReplyPacket checkReply(ReplyPacket reply) { 95 if (reply.getErrorCode() != JDWPConstants.Error.NONE) 96 throw new ReplyErrorCodeException(reply.getErrorCode()); 97 return reply; 98 } 99 100 /** 101 * Sets breakpoint to given location. 102 * 103 * @param typeTag 104 * @param breakpoint 105 * @return ReplyPacket for corresponding command 106 */ setBreakpoint(byte typeTag, Breakpoint breakpoint)107 public ReplyPacket setBreakpoint(byte typeTag, Breakpoint breakpoint) { 108 109 return setBreakpoint(typeTag, breakpoint, 110 JDWPConstants.SuspendPolicy.ALL); 111 } 112 113 /** 114 * Sets breakpoint to given location. 115 * 116 * @param typeTag 117 * @param breakpoint 118 * @param suspendPolicy 119 * Suspend policy for a breakpoint being created 120 * @return ReplyPacket for corresponding command 121 */ setBreakpoint(byte typeTag, Breakpoint breakpoint, byte suspendPolicy)122 public ReplyPacket setBreakpoint(byte typeTag, Breakpoint breakpoint, 123 byte suspendPolicy) { 124 // Get Class reference ID 125 long typeID = getTypeID(breakpoint.className, typeTag); 126 127 // Get Method reference ID 128 long methodID = getMethodID(typeID, breakpoint.methodName); 129 130 // Fill location 131 Location location = new Location(typeTag, typeID, methodID, 132 breakpoint.index); 133 134 // Set breakpoint 135 return setBreakpoint(location, suspendPolicy); 136 } 137 138 /** 139 * Sets breakpoint to given location. 140 * 141 * @param location 142 * Location of breakpoint 143 * @return ReplyPacket for corresponding command 144 */ setBreakpoint(Location location)145 public ReplyPacket setBreakpoint(Location location) { 146 147 return setBreakpoint(location, JDWPConstants.SuspendPolicy.ALL); 148 } 149 150 /** 151 * Sets breakpoint to given location 152 * 153 * @param location 154 * Location of breakpoint 155 * @param suspendPolicy 156 * Suspend policy for a breakpoint being created 157 * @return ReplyPacket for corresponding command 158 */ setBreakpoint(Location location, byte suspendPolicy)159 public ReplyPacket setBreakpoint(Location location, byte suspendPolicy) { 160 // Prepare corresponding event 161 byte eventKind = JDWPConstants.EventKind.BREAKPOINT; 162 163 // EventMod[] mods = new EventMod[1]; 164 EventMod[] mods = new EventMod[] { new EventMod() }; 165 166 mods[0].loc = location; 167 mods[0].modKind = EventMod.ModKind.LocationOnly; 168 Event event = new Event(eventKind, suspendPolicy, mods); 169 170 // Set breakpoint 171 return setEvent(event); 172 } 173 174 /** 175 * Sets breakpoint that triggers only on a certain occurrence to a given 176 * location 177 * 178 * @param typeTag 179 * @param breakpoint 180 * @param suspendPolicy 181 * Suspend policy for a breakpoint being created 182 * @param count 183 * Limit the requested event to be reported at most once after a 184 * given number of occurrences 185 * @return ReplyPacket for corresponding command 186 */ setCountableBreakpoint(byte typeTag, Breakpoint breakpoint, byte suspendPolicy, int count)187 public ReplyPacket setCountableBreakpoint(byte typeTag, 188 Breakpoint breakpoint, byte suspendPolicy, int count) { 189 long typeID = getTypeID(breakpoint.className, typeTag); 190 191 // Get Method reference ID 192 long methodID = getMethodID(typeID, breakpoint.methodName); 193 194 byte eventKind = JDWPConstants.EventKind.BREAKPOINT; 195 196 EventMod mod1 = new EventMod(); 197 mod1.modKind = EventMod.ModKind.LocationOnly; 198 mod1.loc = new Location(typeTag, typeID, methodID, breakpoint.index); 199 200 EventMod mod2 = new EventMod(); 201 mod2.modKind = EventMod.ModKind.Count; 202 mod2.count = count; 203 204 EventMod[] mods = new EventMod[] { mod1, mod2 }; 205 Event event = new Event(eventKind, suspendPolicy, mods); 206 207 // Set breakpoint 208 return setEvent(event); 209 } 210 211 /** 212 * Sets breakpoint at the beginning of method with name <i>methodName</i>. 213 * 214 * @param classID 215 * id of class with required method 216 * @param methodName 217 * name of required method 218 * @return requestID id of request 219 */ setBreakpointAtMethodBegin(long classID, String methodName)220 public int setBreakpointAtMethodBegin(long classID, String methodName) { 221 return setBreakpointAtMethodBegin(classID, methodName, JDWPConstants.SuspendPolicy.ALL); 222 } 223 224 /** 225 * Sets breakpoint at the beginning of method with name <i>methodName</i>. 226 * 227 * @param classID 228 * id of class with required method 229 * @param methodName 230 * name of required method 231 * @return requestID id of request 232 */ setBreakpointAtMethodBegin(long classID, String methodName, byte suspendPolicy)233 public int setBreakpointAtMethodBegin(long classID, String methodName, byte suspendPolicy) { 234 long methodID = getMethodID(classID, methodName); 235 236 ReplyPacket lineTableReply = getLineTable(classID, methodID); 237 if (lineTableReply.getErrorCode() != JDWPConstants.Error.NONE) { 238 throw new TestErrorException( 239 "Command getLineTable returned error code: " 240 + lineTableReply.getErrorCode() 241 + " - " 242 + JDWPConstants.Error.getName(lineTableReply 243 .getErrorCode())); 244 } 245 246 lineTableReply.getNextValueAsLong(); 247 // Lowest valid code index for the method 248 249 lineTableReply.getNextValueAsLong(); 250 // Highest valid code index for the method 251 252 // int numberOfLines = 253 lineTableReply.getNextValueAsInt(); 254 255 long lineCodeIndex = lineTableReply.getNextValueAsLong(); 256 257 // set breakpoint inside checked method 258 Location breakpointLocation = new Location(JDWPConstants.TypeTag.CLASS, 259 classID, methodID, lineCodeIndex); 260 261 ReplyPacket reply = setBreakpoint(breakpointLocation, suspendPolicy); 262 checkReply(reply); 263 264 return reply.getNextValueAsInt(); 265 } 266 267 /** 268 * Waits for stop on breakpoint and gets id of thread where it stopped. 269 * 270 * @param requestID 271 * id of request for breakpoint 272 * @return threadID id of thread, where we stop on breakpoint 273 */ waitForBreakpoint(int requestID)274 public long waitForBreakpoint(int requestID) { 275 // receive event 276 CommandPacket event = null; 277 event = receiveEvent(); 278 279 event.getNextValueAsByte(); 280 // suspendPolicy - is not used here 281 282 // int numberOfEvents = 283 event.getNextValueAsInt(); 284 285 long breakpointThreadID = 0; 286 ParsedEvent[] eventParsed = ParsedEvent.parseEventPacket(event); 287 288 if (eventParsed.length != 1) { 289 throw new TestErrorException("Received " + eventParsed.length 290 + " events instead of 1 BREAKPOINT_EVENT"); 291 } 292 293 // check if received event is for breakpoint 294 if (eventParsed[0].getEventKind() == JDWPConstants.EventKind.BREAKPOINT) { 295 breakpointThreadID = ((ParsedEvent.Event_BREAKPOINT) eventParsed[0]) 296 .getThreadID(); 297 298 } else { 299 throw new TestErrorException( 300 "Kind of received event is not BREAKPOINT_EVENT: " 301 + eventParsed[0].getEventKind()); 302 303 } 304 305 if (eventParsed[0].getRequestID() != requestID) { 306 throw new TestErrorException( 307 "Received BREAKPOINT_EVENT with another requestID: " 308 + eventParsed[0].getRequestID()); 309 } 310 311 return breakpointThreadID; 312 } 313 314 /** 315 * Removes breakpoint according to specified requestID. 316 * 317 * @param requestID 318 * for given breakpoint 319 * @return ReplyPacket for corresponding command 320 */ clearBreakpoint(int requestID)321 public ReplyPacket clearBreakpoint(int requestID) { 322 323 // Create new command packet 324 CommandPacket commandPacket = new CommandPacket(); 325 326 // Set command. "2" - is ID of Clear command in EventRequest Command Set 327 commandPacket 328 .setCommand(JDWPCommands.EventRequestCommandSet.ClearCommand); 329 330 // Set command set. "15" - is ID of EventRequest Command Set 331 commandPacket 332 .setCommandSet(JDWPCommands.EventRequestCommandSet.CommandSetID); 333 334 // Set outgoing data 335 // Set eventKind 336 commandPacket.setNextValueAsByte(JDWPConstants.EventKind.BREAKPOINT); 337 338 // Set suspendPolicy 339 commandPacket.setNextValueAsInt(requestID); 340 341 // Send packet 342 return checkReply(performCommand(commandPacket)); 343 } 344 345 /** 346 * Removes all breakpoints. 347 * 348 * @return ReplyPacket for corresponding command 349 */ ClearAllBreakpoints()350 public ReplyPacket ClearAllBreakpoints() { 351 352 // Create new command packet 353 CommandPacket commandPacket = new CommandPacket(); 354 355 // Set command. "3" - is ID of ClearAllBreakpoints command in 356 // EventRequest Command Set 357 commandPacket 358 .setCommand(JDWPCommands.EventRequestCommandSet.ClearAllBreakpointsCommand); 359 360 // Set command set. "15" - is ID of EventRequest Command Set 361 commandPacket 362 .setCommandSet(JDWPCommands.EventRequestCommandSet.CommandSetID); 363 364 // Send packet 365 return checkReply(performCommand(commandPacket)); 366 } 367 368 /** 369 * Requests debuggee VM capabilities. Function parses reply packet of 370 * VirtualMachine::CapabilitiesNew command, creates and fills class 371 * Capabilities with returned info. 372 * 373 * @return ReplyPacket useless, already parsed reply packet. 374 */ capabilities()375 public ReplyPacket capabilities() { 376 377 // Create new command packet 378 CommandPacket commandPacket = new CommandPacket(); 379 380 // Set command. "17" - is ID of CapabilitiesNew command in 381 // VirtualMachine Command Set 382 commandPacket 383 .setCommand(JDWPCommands.VirtualMachineCommandSet.CapabilitiesNewCommand); 384 385 // Set command set. "1" - is ID of VirtualMachine Command Set 386 commandPacket 387 .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID); 388 389 // Send packet 390 ReplyPacket replyPacket = checkReply(performCommand(commandPacket)); 391 392 targetVMCapabilities = new Capabilities(); 393 394 // Set capabilities 395 targetVMCapabilities.canWatchFieldModification = replyPacket 396 .getNextValueAsBoolean(); 397 targetVMCapabilities.canWatchFieldAccess = replyPacket 398 .getNextValueAsBoolean(); 399 targetVMCapabilities.canGetBytecodes = replyPacket 400 .getNextValueAsBoolean(); 401 targetVMCapabilities.canGetSyntheticAttribute = replyPacket 402 .getNextValueAsBoolean(); 403 targetVMCapabilities.canGetOwnedMonitorInfo = replyPacket 404 .getNextValueAsBoolean(); 405 targetVMCapabilities.canGetCurrentContendedMonitor = replyPacket 406 .getNextValueAsBoolean(); 407 targetVMCapabilities.canGetMonitorInfo = replyPacket 408 .getNextValueAsBoolean(); 409 targetVMCapabilities.canRedefineClasses = replyPacket 410 .getNextValueAsBoolean(); 411 targetVMCapabilities.canAddMethod = replyPacket.getNextValueAsBoolean(); 412 targetVMCapabilities.canUnrestrictedlyRedefineClasses = replyPacket 413 .getNextValueAsBoolean(); 414 targetVMCapabilities.canPopFrames = replyPacket.getNextValueAsBoolean(); 415 targetVMCapabilities.canUseInstanceFilters = replyPacket 416 .getNextValueAsBoolean(); 417 targetVMCapabilities.canGetSourceDebugExtension = replyPacket 418 .getNextValueAsBoolean(); 419 targetVMCapabilities.canRequestVMDeathEvent = replyPacket 420 .getNextValueAsBoolean(); 421 targetVMCapabilities.canSetDefaultStratum = replyPacket 422 .getNextValueAsBoolean(); 423 targetVMCapabilities.canGetInstanceInfo = replyPacket 424 .getNextValueAsBoolean(); 425 targetVMCapabilities.reserved17 = replyPacket.getNextValueAsBoolean(); 426 targetVMCapabilities.canGetMonitorFrameInfo = replyPacket 427 .getNextValueAsBoolean(); 428 targetVMCapabilities.canUseSourceNameFilters = replyPacket.getNextValueAsBoolean(); 429 targetVMCapabilities.canGetConstantPool = replyPacket 430 .getNextValueAsBoolean(); 431 targetVMCapabilities.canForceEarlyReturn = replyPacket 432 .getNextValueAsBoolean(); 433 targetVMCapabilities.reserved22 = replyPacket.getNextValueAsBoolean(); 434 targetVMCapabilities.reserved23 = replyPacket.getNextValueAsBoolean(); 435 targetVMCapabilities.reserved24 = replyPacket.getNextValueAsBoolean(); 436 targetVMCapabilities.reserved25 = replyPacket.getNextValueAsBoolean(); 437 targetVMCapabilities.reserved26 = replyPacket.getNextValueAsBoolean(); 438 targetVMCapabilities.reserved27 = replyPacket.getNextValueAsBoolean(); 439 targetVMCapabilities.reserved28 = replyPacket.getNextValueAsBoolean(); 440 targetVMCapabilities.reserved29 = replyPacket.getNextValueAsBoolean(); 441 targetVMCapabilities.reserved30 = replyPacket.getNextValueAsBoolean(); 442 targetVMCapabilities.reserved31 = replyPacket.getNextValueAsBoolean(); 443 targetVMCapabilities.reserved32 = replyPacket.getNextValueAsBoolean(); 444 445 return replyPacket; 446 } 447 canWatchFieldModification()448 public boolean canWatchFieldModification() { 449 capabilities(); 450 return targetVMCapabilities.canWatchFieldModification; 451 } 452 canWatchFieldAccess()453 public boolean canWatchFieldAccess() { 454 capabilities(); 455 return targetVMCapabilities.canWatchFieldAccess; 456 } 457 canUseInstanceFilters()458 public boolean canUseInstanceFilters() { 459 capabilities(); 460 return targetVMCapabilities.canUseInstanceFilters; 461 } 462 463 /** 464 * Resumes debuggee VM. 465 * 466 * @return ReplyPacket for corresponding command 467 */ resume()468 public ReplyPacket resume() { 469 CommandPacket commandPacket = new CommandPacket( 470 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 471 JDWPCommands.VirtualMachineCommandSet.ResumeCommand); 472 473 return checkReply(performCommand(commandPacket)); 474 } 475 476 /** 477 * Resumes specified thread on target Virtual Machine 478 * 479 * @return ReplyPacket for corresponding command 480 */ resumeThread(long threadID)481 public ReplyPacket resumeThread(long threadID) { 482 CommandPacket commandPacket = new CommandPacket( 483 JDWPCommands.ThreadReferenceCommandSet.CommandSetID, 484 JDWPCommands.ThreadReferenceCommandSet.ResumeCommand); 485 486 commandPacket.setNextValueAsThreadID(threadID); 487 return checkReply(performCommand(commandPacket)); 488 } 489 490 /** 491 * Suspends debuggee VM. 492 * 493 * @return ReplyPacket for corresponding command 494 */ suspend()495 public ReplyPacket suspend() { 496 CommandPacket commandPacket = new CommandPacket( 497 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 498 JDWPCommands.VirtualMachineCommandSet.SuspendCommand); 499 500 return checkReply(performCommand(commandPacket)); 501 } 502 503 /** 504 * Suspends specified thread in debuggee VM. 505 * 506 * @return ReplyPacket for corresponding command 507 */ suspendThread(long threadID)508 public ReplyPacket suspendThread(long threadID) { 509 CommandPacket commandPacket = new CommandPacket( 510 JDWPCommands.ThreadReferenceCommandSet.CommandSetID, 511 JDWPCommands.ThreadReferenceCommandSet.SuspendCommand); 512 513 commandPacket.setNextValueAsThreadID(threadID); 514 return checkReply(performCommand(commandPacket)); 515 } 516 517 /** 518 * Disposes connection to debuggee VM. 519 * 520 * @return ReplyPacket for corresponding command 521 */ dispose()522 public ReplyPacket dispose() { 523 // Create new command packet 524 CommandPacket commandPacket = new CommandPacket(); 525 commandPacket 526 .setCommand(JDWPCommands.VirtualMachineCommandSet.DisposeCommand); 527 commandPacket 528 .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID); 529 530 // Send packet 531 return checkReply(performCommand(commandPacket)); 532 } 533 534 /** 535 * Exits debuggee VM process. 536 * 537 * @return ReplyPacket for corresponding command 538 */ exit(int exitCode)539 public ReplyPacket exit(int exitCode) { 540 // Create new command packet 541 CommandPacket commandPacket = new CommandPacket(); 542 commandPacket 543 .setCommand(JDWPCommands.VirtualMachineCommandSet.ExitCommand); 544 commandPacket 545 .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID); 546 commandPacket.setNextValueAsInt(exitCode); 547 548 // Send packet 549 return checkReply(performCommand(commandPacket)); 550 } 551 552 /** 553 * Adjusts lengths for all VM-specific types. 554 * 555 * @return ReplyPacket for corresponding command 556 */ adjustTypeLength()557 public ReplyPacket adjustTypeLength() { 558 // Create new command packet 559 CommandPacket commandPacket = new CommandPacket(); 560 commandPacket 561 .setCommand(JDWPCommands.VirtualMachineCommandSet.IDSizesCommand); 562 commandPacket 563 .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID); 564 565 // Send packet 566 ReplyPacket replyPacket = checkReply(performCommand(commandPacket)); 567 568 // Get FieldIDSize from ReplyPacket 569 TypesLengths.setTypeLength(TypesLengths.FIELD_ID, replyPacket 570 .getNextValueAsInt()); 571 572 // Get MethodIDSize from ReplyPacket 573 TypesLengths.setTypeLength(TypesLengths.METHOD_ID, replyPacket 574 .getNextValueAsInt()); 575 576 // Get ObjectIDSize from ReplyPacket 577 TypesLengths.setTypeLength(TypesLengths.OBJECT_ID, replyPacket 578 .getNextValueAsInt()); 579 580 // Get ReferenceTypeIDSize from ReplyPacket 581 TypesLengths.setTypeLength(TypesLengths.REFERENCE_TYPE_ID, replyPacket 582 .getNextValueAsInt()); 583 584 // Get FrameIDSize from ReplyPacket 585 TypesLengths.setTypeLength(TypesLengths.FRAME_ID, replyPacket 586 .getNextValueAsInt()); 587 588 // Adjust all other types lengths 589 TypesLengths.setTypeLength(TypesLengths.ARRAY_ID, TypesLengths 590 .getTypeLength(TypesLengths.OBJECT_ID)); 591 TypesLengths.setTypeLength(TypesLengths.STRING_ID, TypesLengths 592 .getTypeLength(TypesLengths.OBJECT_ID)); 593 TypesLengths.setTypeLength(TypesLengths.THREAD_ID, TypesLengths 594 .getTypeLength(TypesLengths.OBJECT_ID)); 595 TypesLengths.setTypeLength(TypesLengths.THREADGROUP_ID, TypesLengths 596 .getTypeLength(TypesLengths.OBJECT_ID)); 597 TypesLengths.setTypeLength(TypesLengths.LOCATION_ID, TypesLengths 598 .getTypeLength(TypesLengths.OBJECT_ID)); 599 TypesLengths.setTypeLength(TypesLengths.CLASS_ID, TypesLengths 600 .getTypeLength(TypesLengths.OBJECT_ID)); 601 TypesLengths.setTypeLength(TypesLengths.CLASSLOADER_ID, TypesLengths 602 .getTypeLength(TypesLengths.OBJECT_ID)); 603 TypesLengths.setTypeLength(TypesLengths.CLASSOBJECT_ID, TypesLengths 604 .getTypeLength(TypesLengths.OBJECT_ID)); 605 return replyPacket; 606 } 607 608 /** 609 * Gets TypeID for specified type signature and type tag. 610 * 611 * @param typeSignature 612 * type signature 613 * @param classTypeTag 614 * type tag 615 * @return received TypeID 616 */ getTypeID(String typeSignature, byte classTypeTag)617 public long getTypeID(String typeSignature, byte classTypeTag) { 618 int classes = 0; 619 byte refTypeTag = 0; 620 long typeID = -1; 621 622 // Request referenceTypeID for exception 623 ReplyPacket classReference = getClassBySignature(typeSignature); 624 625 // Get referenceTypeID from received packet 626 classes = classReference.getNextValueAsInt(); 627 for (int i = 0; i < classes; i++) { 628 refTypeTag = classReference.getNextValueAsByte(); 629 if (refTypeTag == classTypeTag) { 630 typeID = classReference.getNextValueAsReferenceTypeID(); 631 classReference.getNextValueAsInt(); 632 break; 633 } else { 634 classReference.getNextValueAsReferenceTypeID(); 635 classReference.getNextValueAsInt(); 636 refTypeTag = 0; 637 } 638 } 639 return typeID; 640 } 641 642 /** 643 * Gets ClassID for specified class signature. 644 * 645 * @param classSignature 646 * class signature 647 * @return received ClassID 648 */ getClassID(String classSignature)649 public long getClassID(String classSignature) { 650 return getTypeID(classSignature, JDWPConstants.TypeTag.CLASS); 651 } 652 653 /** 654 * Gets ThreadID for specified thread name. 655 * 656 * @param threadName 657 * thread name 658 * @return received ThreadID 659 */ getThreadID(String threadName)660 public long getThreadID(String threadName) { 661 ReplyPacket request = null; 662 long threadID = -1; 663 long thread = -1; 664 String name = null; 665 int threads = -1; 666 667 // Get All Threads IDs 668 request = getAllThreadID(); 669 670 // Get thread ID for threadName 671 threads = request.getNextValueAsInt(); 672 for (int i = 0; i < threads; i++) { 673 thread = request.getNextValueAsThreadID(); 674 name = getThreadName(thread); 675 if (threadName.equals(name)) { 676 threadID = thread; 677 break; 678 } 679 } 680 681 return threadID; 682 } 683 684 /** 685 * Returns all running thread IDs. 686 * 687 * @return received reply packet 688 */ getAllThreadID()689 public ReplyPacket getAllThreadID() { 690 // Create new command packet 691 CommandPacket commandPacket = new CommandPacket( 692 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 693 JDWPCommands.VirtualMachineCommandSet.AllThreadsCommand); 694 695 return checkReply(performCommand(commandPacket)); 696 } 697 698 /** 699 * Gets class signature for specified class ID. 700 * 701 * @param classID 702 * class ID 703 * @return received class signature 704 */ getClassSignature(long classID)705 public String getClassSignature(long classID) { 706 // Create new command packet 707 CommandPacket commandPacket = new CommandPacket( 708 JDWPCommands.ReferenceTypeCommandSet.CommandSetID, 709 JDWPCommands.ReferenceTypeCommandSet.SignatureCommand); 710 commandPacket.setNextValueAsReferenceTypeID(classID); 711 ReplyPacket replyPacket = checkReply(performCommand(commandPacket)); 712 return replyPacket.getNextValueAsString(); 713 } 714 715 /** 716 * Returns thread name for specified <code>threadID</code>. 717 * 718 * @param threadID 719 * thread ID 720 * @return thread name 721 */ getThreadName(long threadID)722 public String getThreadName(long threadID) { 723 // Create new command packet 724 CommandPacket commandPacket = new CommandPacket( 725 JDWPCommands.ThreadReferenceCommandSet.CommandSetID, 726 JDWPCommands.ThreadReferenceCommandSet.NameCommand); 727 commandPacket.setNextValueAsThreadID(threadID); 728 ReplyPacket replyPacket = checkReply(performCommand(commandPacket)); 729 return replyPacket.getNextValueAsString(); 730 } 731 732 /** 733 * Returns thread status for specified <code>threadID</code>. 734 * 735 * @param threadID 736 * thread ID 737 * @return thread status 738 */ getThreadStatus(long threadID)739 public int getThreadStatus(long threadID) { 740 CommandPacket commandPacket = new CommandPacket( 741 JDWPCommands.ThreadReferenceCommandSet.CommandSetID, 742 JDWPCommands.ThreadReferenceCommandSet.StatusCommand); 743 commandPacket.setNextValueAsThreadID(threadID); 744 ReplyPacket replyPacket = checkReply(performCommand(commandPacket)); 745 return replyPacket.getNextValueAsInt(); 746 } 747 748 /** 749 * Returns suspend count for specified <code>threadID</code>. 750 * 751 * @param threadID 752 * thread ID 753 * @return thread's suspend count 754 */ getThreadSuspendCount(long threadID)755 public int getThreadSuspendCount(long threadID) { 756 CommandPacket commandPacket = new CommandPacket( 757 JDWPCommands.ThreadReferenceCommandSet.CommandSetID, 758 JDWPCommands.ThreadReferenceCommandSet.SuspendCountCommand); 759 commandPacket.setNextValueAsThreadID(threadID); 760 ReplyPacket replyPacket = checkReply(performCommand(commandPacket)); 761 return replyPacket.getNextValueAsInt(); 762 } 763 764 /** 765 * Returns name of thread group for specified <code>groupID</code> 766 * 767 * @param groupID 768 * thread group ID 769 * 770 * @return name of thread group 771 */ getThreadGroupName(long groupID)772 public String getThreadGroupName(long groupID) { 773 // Create new command packet 774 CommandPacket commandPacket = new CommandPacket( 775 JDWPCommands.ThreadGroupReferenceCommandSet.CommandSetID, 776 JDWPCommands.ThreadGroupReferenceCommandSet.NameCommand); 777 commandPacket.setNextValueAsReferenceTypeID(groupID); 778 ReplyPacket replyPacket = checkReply(performCommand(commandPacket)); 779 return replyPacket.getNextValueAsString(); 780 } 781 782 /** 783 * Gets InterfaceID for specified interface signature. 784 * 785 * @param interfaceSignature 786 * interface signature 787 * @return received ClassID 788 */ getInterfaceID(String interfaceSignature)789 public long getInterfaceID(String interfaceSignature) { 790 return getTypeID(interfaceSignature, JDWPConstants.TypeTag.INTERFACE); 791 } 792 793 /** 794 * Gets ArrayID for specified array signature. 795 * 796 * @param arraySignature 797 * array signature 798 * @return received ArrayID 799 */ getArrayID(String arraySignature)800 public long getArrayID(String arraySignature) { 801 return getTypeID(arraySignature, JDWPConstants.TypeTag.INTERFACE); 802 } 803 804 /** 805 * Gets RequestID from specified ReplyPacket. 806 * 807 * @param request 808 * ReplyPacket with RequestID 809 * @return received RequestID 810 */ getRequestID(ReplyPacket request)811 public int getRequestID(ReplyPacket request) { 812 return request.getNextValueAsInt(); 813 } 814 815 /** 816 * Returns FieldID for specified class and field name. 817 * 818 * @param classID 819 * ClassID to find field 820 * @param fieldName 821 * field name 822 * @return received FieldID 823 */ getFieldID(long classID, String fieldName)824 public long getFieldID(long classID, String fieldName) { 825 ReplyPacket reply = getFieldsInClass(classID); 826 return getFieldID(reply, fieldName); 827 } 828 829 /** 830 * Gets FieldID from ReplyPacket. 831 * 832 * @param request 833 * ReplyPacket for request 834 * @param field 835 * field name to get ID for 836 * @return received FieldID 837 */ getFieldID(ReplyPacket request, String field)838 public long getFieldID(ReplyPacket request, String field) { 839 long fieldID = -1; 840 String fieldName; 841 // Get fieldID from received packet 842 int count = request.getNextValueAsInt(); 843 for (int i = 0; i < count; i++) { 844 fieldID = request.getNextValueAsFieldID(); 845 fieldName = request.getNextValueAsString(); 846 if (field.equals(fieldName)) { 847 request.getNextValueAsString(); 848 request.getNextValueAsInt(); 849 break; 850 } else { 851 request.getNextValueAsString(); 852 request.getNextValueAsInt(); 853 fieldID = 0; 854 fieldName = null; 855 } 856 } 857 return fieldID; 858 } 859 860 /** 861 * Gets Method ID for specified class and method name. 862 * 863 * @param classID 864 * class to find method 865 * @param methodName 866 * method name 867 * @return received MethodID 868 */ getMethodID(long classID, String methodName)869 public long getMethodID(long classID, String methodName) { 870 ReplyPacket reply; 871 int declared = 0; 872 String method = null; 873 long methodID = -1; 874 875 // Get Method reference ID 876 reply = getMethods(classID); 877 878 // Get methodID from received packet 879 declared = reply.getNextValueAsInt(); 880 for (int i = 0; i < declared; i++) { 881 methodID = reply.getNextValueAsMethodID(); 882 method = reply.getNextValueAsString(); 883 if (methodName.equals(method)) { 884 // If this method name is the same as requested 885 reply.getNextValueAsString(); 886 reply.getNextValueAsInt(); 887 break; 888 } else { 889 // If this method name is not the requested one 890 reply.getNextValueAsString(); 891 reply.getNextValueAsInt(); 892 methodID = -1; 893 method = null; 894 } 895 } 896 return methodID; 897 } 898 899 /** 900 * Returns method name for specified pair of classID and methodID. 901 * 902 * @param classID 903 * @param methodID 904 * @return method name 905 */ getMethodName(long classID, long methodID)906 public String getMethodName(long classID, long methodID) { 907 CommandPacket packet = new CommandPacket( 908 JDWPCommands.ReferenceTypeCommandSet.CommandSetID, 909 JDWPCommands.ReferenceTypeCommandSet.MethodsCommand); 910 packet.setNextValueAsReferenceTypeID(classID); 911 ReplyPacket reply = performCommand(packet); 912 913 int declared = reply.getNextValueAsInt(); 914 long mID; 915 String value = null; 916 String methodName = ""; 917 for (int i = 0; i < declared; i++) { 918 mID = reply.getNextValueAsMethodID(); 919 methodName = reply.getNextValueAsString(); 920 reply.getNextValueAsString(); 921 reply.getNextValueAsInt(); 922 if (mID == methodID) { 923 value = methodName; 924 break; 925 } 926 } 927 return value; 928 } 929 930 /** 931 * Sets ClassPrepare event request for given class name pattern. 932 * 933 * @param classRegexp 934 * Required class pattern. Matches are limited to exact matches 935 * of the given class pattern and matches of patterns that begin 936 * or end with '*'; for example, "*.Foo" or "java.*". 937 * @return ReplyPacket for setting request. 938 */ setClassPrepared(String classRegexp)939 public ReplyPacket setClassPrepared(String classRegexp) { 940 // Prepare corresponding event 941 byte eventKind = JDWPConstants.EventKind.CLASS_PREPARE; 942 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 943 // EventMod[] mods = new EventMod[1]; 944 EventMod[] mods = new EventMod[] { new EventMod() }; 945 mods[0].classPattern = classRegexp; 946 mods[0].modKind = EventMod.ModKind.ClassMatch; 947 Event event = new Event(eventKind, suspendPolicy, mods); 948 949 // Set event 950 return setEvent(event); 951 } 952 953 /** 954 * Set ClassPrepare event request for given class ID. 955 * 956 * @param referenceTypeID 957 * class referenceTypeID 958 * @return ReplyPacket for setting request 959 */ setClassPrepared(long referenceTypeID)960 public ReplyPacket setClassPrepared(long referenceTypeID) { 961 // Prepare corresponding event 962 byte eventKind = JDWPConstants.EventKind.CLASS_PREPARE; 963 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 964 // EventMod[] mods = new EventMod[1]; 965 EventMod[] mods = new EventMod[] { new EventMod() }; 966 mods[0].clazz = referenceTypeID; 967 mods[0].modKind = EventMod.ModKind.ClassOnly; 968 Event event = new Event(eventKind, suspendPolicy, mods); 969 970 // Set event 971 return setEvent(event); 972 } 973 974 /** 975 * Sets ClassPrepare event request for given source name pattern. 976 * 977 * @param sourceNamePattern 978 * Required source name pattern. Matches are limited to exact matches 979 * of the given source name pattern and matches of patterns that begin 980 * or end with '*'; for example, "*.Foo" or "java.*". 981 * @return ReplyPacket for setting request. 982 */ setClassPreparedForSourceNameMatch(String sourceNamePattern)983 public ReplyPacket setClassPreparedForSourceNameMatch(String sourceNamePattern) { 984 // Prepare corresponding event 985 byte eventKind = JDWPConstants.EventKind.CLASS_PREPARE; 986 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 987 EventMod[] mods = new EventMod[] { new EventMod() }; 988 mods[0].sourceNamePattern = sourceNamePattern; 989 mods[0].modKind = EventMod.ModKind.SourceNameMatch; 990 Event event = new Event(eventKind, suspendPolicy, mods); 991 992 // Set event 993 return setEvent(event); 994 } 995 996 /** 997 * Sets ClassUnload event request for given class name pattern. 998 * 999 * @param classSignature 1000 * class signature 1001 * @return ReplyPacket for setting request 1002 */ setClassUnload(String classRegexp)1003 public ReplyPacket setClassUnload(String classRegexp) { 1004 // Prepare corresponding event 1005 byte eventKind = JDWPConstants.EventKind.CLASS_UNLOAD; 1006 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1007 // EventMod[] mods = new EventMod[1]; 1008 EventMod[] mods = new EventMod[] { new EventMod() }; 1009 mods[0].classPattern = classRegexp; 1010 mods[0].modKind = EventMod.ModKind.ClassMatch; 1011 Event event = new Event(eventKind, suspendPolicy, mods); 1012 1013 // Set event 1014 return setEvent(event); 1015 } 1016 1017 /** 1018 * Set ClassUnload event request for given class ID. 1019 * 1020 * @param referenceTypeID 1021 * class referenceTypeID 1022 * @return ReplyPacket for setting request 1023 */ setClassUnload(long referenceTypeID)1024 public ReplyPacket setClassUnload(long referenceTypeID) { 1025 // Prepare corresponding event 1026 byte eventKind = JDWPConstants.EventKind.CLASS_UNLOAD; 1027 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1028 // EventMod[] mods = new EventMod[1]; 1029 EventMod[] mods = new EventMod[] { new EventMod() }; 1030 mods[0].clazz = referenceTypeID; 1031 mods[0].modKind = EventMod.ModKind.ClassOnly; 1032 Event event = new Event(eventKind, suspendPolicy, mods); 1033 1034 // Set event 1035 return setEvent(event); 1036 } 1037 1038 /** 1039 * Sets ClassLoad event request for given class signature. 1040 * 1041 * @param classSignature 1042 * class signature 1043 * @return ReplyPacket for setting request 1044 */ setClassLoad(String classSignature)1045 public ReplyPacket setClassLoad(String classSignature) { 1046 long typeID; 1047 1048 // Request referenceTypeID for class 1049 typeID = getClassID(classSignature); 1050 1051 // Set corresponding event 1052 return setClassLoad(typeID); 1053 } 1054 1055 /** 1056 * Set ClassLoad event request for given class ID. 1057 * 1058 * @param referenceTypeID 1059 * class referenceTypeID 1060 * @return ReplyPacket for setting request 1061 */ setClassLoad(long referenceTypeID)1062 public ReplyPacket setClassLoad(long referenceTypeID) { 1063 // Prepare corresponding event 1064 byte eventKind = JDWPConstants.EventKind.CLASS_LOAD; 1065 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1066 EventMod[] mods = new EventMod[] { new EventMod() }; 1067 mods[0].clazz = referenceTypeID; 1068 mods[0].modKind = EventMod.ModKind.ClassOnly; 1069 Event event = new Event(eventKind, suspendPolicy, mods); 1070 1071 // Set event 1072 return setEvent(event); 1073 } 1074 1075 /** 1076 * Set MonitorContendedEnter event request for given class's reference type 1077 * 1078 * @param referenceTypeID 1079 * class referenceTypeID 1080 * @return ReplyPacket for setting request 1081 */ setMonitorContendedEnterForClassOnly(long referenceTypeID)1082 public ReplyPacket setMonitorContendedEnterForClassOnly(long referenceTypeID) { 1083 // Prepare corresponding event 1084 byte eventKind = JDWPConstants.EventKind.MONITOR_CONTENDED_ENTER; 1085 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1086 EventMod[] mods = new EventMod[] { new EventMod() }; 1087 mods[0].clazz = referenceTypeID; 1088 mods[0].modKind = EventMod.ModKind.ClassOnly; 1089 Event event = new Event(eventKind, suspendPolicy, mods); 1090 1091 // Set event 1092 return setEvent(event); 1093 } 1094 setMonitorContendedEnterForClassMatch(String classRegexp)1095 public ReplyPacket setMonitorContendedEnterForClassMatch(String classRegexp) { 1096 // Prepare corresponding event 1097 byte eventKind = JDWPConstants.EventKind.MONITOR_CONTENDED_ENTER; 1098 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1099 EventMod[] mods = new EventMod[] { new EventMod() }; 1100 mods[0].classPattern = classRegexp; 1101 mods[0].modKind = EventMod.ModKind.ClassMatch; 1102 Event event = new Event(eventKind, suspendPolicy, mods); 1103 1104 // Set event 1105 return setEvent(event); 1106 } 1107 1108 /** 1109 * Set MonitorContendedEntered event request for given class's reference type 1110 * 1111 * @param referenceTypeID 1112 * class referenceTypeID 1113 * @return ReplyPacket for setting request 1114 */ setMonitorContendedEnteredForClassOnly(long referenceTypeID)1115 public ReplyPacket setMonitorContendedEnteredForClassOnly(long referenceTypeID) { 1116 // Prepare corresponding event 1117 byte eventKind = JDWPConstants.EventKind.MONITOR_CONTENDED_ENTERED; 1118 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1119 EventMod[] mods = new EventMod[] { new EventMod() }; 1120 mods[0].clazz = referenceTypeID; 1121 mods[0].modKind = EventMod.ModKind.ClassOnly; 1122 Event event = new Event(eventKind, suspendPolicy, mods); 1123 1124 // Set event 1125 return setEvent(event); 1126 } 1127 setMonitorContendedEnteredForClassMatch(String classRegexp)1128 public ReplyPacket setMonitorContendedEnteredForClassMatch(String classRegexp) { 1129 // Prepare corresponding event 1130 byte eventKind = JDWPConstants.EventKind.MONITOR_CONTENDED_ENTERED; 1131 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1132 EventMod[] mods = new EventMod[] { new EventMod() }; 1133 mods[0].classPattern = classRegexp; 1134 mods[0].modKind = EventMod.ModKind.ClassMatch; 1135 Event event = new Event(eventKind, suspendPolicy, mods); 1136 1137 // Set event 1138 return setEvent(event); 1139 } 1140 1141 /** 1142 * Set MonitorWait event request for given class's reference type 1143 * 1144 * @param referenceTypeID 1145 * class referenceTypeID 1146 * @return ReplyPacket for setting request 1147 */ setMonitorWaitForClassOnly(long referenceTypeID)1148 public ReplyPacket setMonitorWaitForClassOnly(long referenceTypeID) { 1149 // Prepare corresponding event 1150 byte eventKind = JDWPConstants.EventKind.MONITOR_WAIT; 1151 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1152 EventMod[] mods = new EventMod[] { new EventMod() }; 1153 mods[0].clazz = referenceTypeID; 1154 mods[0].modKind = EventMod.ModKind.ClassOnly; 1155 Event event = new Event(eventKind, suspendPolicy, mods); 1156 1157 // Set event 1158 return setEvent(event); 1159 } 1160 1161 /** 1162 * Set MonitorWait event request for given given class name pattern. 1163 * 1164 * @param classRegexp 1165 * Required class pattern. Matches are limited to exact matches 1166 * of the given class pattern and matches of patterns that begin 1167 * or end with '*'; for example, "*.Foo" or "java.*". 1168 * @return ReplyPacket for setting request. 1169 */ setMonitorWaitForClassMatch(String classRegexp)1170 public ReplyPacket setMonitorWaitForClassMatch(String classRegexp) { 1171 // Prepare corresponding event 1172 byte eventKind = JDWPConstants.EventKind.MONITOR_WAIT; 1173 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1174 EventMod[] mods = new EventMod[] { new EventMod() }; 1175 mods[0].classPattern = classRegexp; 1176 mods[0].modKind = EventMod.ModKind.ClassMatch; 1177 Event event = new Event(eventKind, suspendPolicy, mods); 1178 1179 // Set event 1180 return setEvent(event); 1181 } 1182 1183 /** 1184 * Set MonitorWait event request for classes 1185 * whose name does not match the given restricted regular expression. 1186 * 1187 * @param classRegexp 1188 * Exclude class pattern. Matches are limited to exact matches 1189 * of the given class pattern and matches of patterns that begin 1190 * or end with '*'; for example, "*.Foo" or "java.*". 1191 * @return ReplyPacket for setting request. 1192 */ setMonitorWaitForClassExclude(String classRegexp)1193 public ReplyPacket setMonitorWaitForClassExclude (String classRegexp) { 1194 // Prepare corresponding event 1195 byte eventKind = JDWPConstants.EventKind.MONITOR_WAIT; 1196 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1197 EventMod[] mods = new EventMod[] { new EventMod() }; 1198 mods[0].classPattern = classRegexp; 1199 mods[0].modKind = EventMod.ModKind.ClassExclude; 1200 Event event = new Event(eventKind, suspendPolicy, mods); 1201 1202 // Set event 1203 return setEvent(event); 1204 } 1205 1206 /** 1207 * Set MonitorWaited event request for given class's reference type 1208 * 1209 * @param referenceTypeID 1210 * class referenceTypeID 1211 * @return ReplyPacket for setting request 1212 */ setMonitorWaitedForClassOnly(long referenceTypeID)1213 public ReplyPacket setMonitorWaitedForClassOnly(long referenceTypeID) { 1214 // Prepare corresponding event 1215 byte eventKind = JDWPConstants.EventKind.MONITOR_WAITED; 1216 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1217 EventMod[] mods = new EventMod[] { new EventMod() }; 1218 mods[0].clazz = referenceTypeID; 1219 mods[0].modKind = EventMod.ModKind.ClassOnly; 1220 Event event = new Event(eventKind, suspendPolicy, mods); 1221 1222 // Set event 1223 return setEvent(event); 1224 } 1225 1226 /** 1227 * Set MonitorWaited event request for given given source name pattern. 1228 * 1229 * @param classRegexp 1230 * Required class pattern. Matches are limited to exact matches 1231 * of the given class pattern and matches of patterns that begin 1232 * or end with '*'; for example, "*.Foo" or "java.*". 1233 * @return ReplyPacket for setting request. 1234 */ setMonitorWaitedForClassMatch(String classRegexp)1235 public ReplyPacket setMonitorWaitedForClassMatch(String classRegexp) { 1236 // Prepare corresponding event 1237 byte eventKind = JDWPConstants.EventKind.MONITOR_WAITED; 1238 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1239 EventMod[] mods = new EventMod[] { new EventMod() }; 1240 mods[0].classPattern = classRegexp; 1241 mods[0].modKind = EventMod.ModKind.ClassMatch; 1242 Event event = new Event(eventKind, suspendPolicy, mods); 1243 1244 // Set event 1245 return setEvent(event); 1246 } 1247 1248 /** 1249 * Set MonitorWaited event request for classes 1250 * whose name does not match the given restricted regular expression. 1251 * 1252 * @param classRegexp 1253 * Required class pattern. Matches are limited to exact matches 1254 * of the given class pattern and matches of patterns that begin 1255 * or end with '*'; for example, "*.Foo" or "java.*". 1256 * @return ReplyPacket for setting request. 1257 */ setMonitorWaitedForClassExclude(String classRegexp)1258 public ReplyPacket setMonitorWaitedForClassExclude (String classRegexp) { 1259 // Prepare corresponding event 1260 byte eventKind = JDWPConstants.EventKind.MONITOR_WAITED; 1261 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1262 EventMod[] mods = new EventMod[] { new EventMod() }; 1263 mods[0].classPattern = classRegexp; 1264 mods[0].modKind = EventMod.ModKind.ClassExclude; 1265 Event event = new Event(eventKind, suspendPolicy, mods); 1266 1267 // Set event 1268 return setEvent(event); 1269 } 1270 1271 /** 1272 * Set event request for given event. 1273 * 1274 * @param event 1275 * event to set request for 1276 * @return ReplyPacket for setting request 1277 */ setEvent(Event event)1278 public ReplyPacket setEvent(Event event) { 1279 // Create new command packet 1280 CommandPacket commandPacket = new CommandPacket( 1281 JDWPCommands.EventRequestCommandSet.CommandSetID, 1282 JDWPCommands.EventRequestCommandSet.SetCommand); 1283 1284 // Set eventKind 1285 commandPacket.setNextValueAsByte(event.eventKind); 1286 // Set suspendPolicy 1287 commandPacket.setNextValueAsByte(event.suspendPolicy); 1288 1289 // Set modifiers 1290 commandPacket.setNextValueAsInt(event.modifiers); 1291 1292 for (int i = 0; i < event.modifiers; i++) { 1293 1294 commandPacket.setNextValueAsByte(event.mods[i].modKind); 1295 1296 switch (event.mods[i].modKind) { 1297 case EventMod.ModKind.Count: { 1298 // Case Count 1299 commandPacket.setNextValueAsInt(event.mods[i].count); 1300 break; 1301 } 1302 case EventMod.ModKind.Conditional: { 1303 // Case Conditional 1304 commandPacket.setNextValueAsInt(event.mods[i].exprID); 1305 break; 1306 } 1307 case EventMod.ModKind.ThreadOnly: { 1308 // Case ThreadOnly 1309 commandPacket.setNextValueAsThreadID(event.mods[i].thread); 1310 break; 1311 } 1312 case EventMod.ModKind.ClassOnly: { 1313 // Case ClassOnly 1314 commandPacket 1315 .setNextValueAsReferenceTypeID(event.mods[i].clazz); 1316 break; 1317 } 1318 case EventMod.ModKind.ClassMatch: { 1319 // Case ClassMatch 1320 commandPacket.setNextValueAsString(event.mods[i].classPattern); 1321 break; 1322 } 1323 case EventMod.ModKind.ClassExclude: { 1324 // Case ClassExclude 1325 commandPacket.setNextValueAsString(event.mods[i].classPattern); 1326 break; 1327 } 1328 case EventMod.ModKind.LocationOnly: { 1329 // Case LocationOnly 1330 commandPacket.setNextValueAsLocation(event.mods[i].loc); 1331 break; 1332 } 1333 case EventMod.ModKind.ExceptionOnly: 1334 // Case ExceptionOnly 1335 commandPacket 1336 .setNextValueAsReferenceTypeID(event.mods[i].exceptionOrNull); 1337 commandPacket.setNextValueAsBoolean(event.mods[i].caught); 1338 commandPacket.setNextValueAsBoolean(event.mods[i].uncaught); 1339 break; 1340 case EventMod.ModKind.FieldOnly: { 1341 // Case FieldOnly 1342 commandPacket 1343 .setNextValueAsReferenceTypeID(event.mods[i].declaring); 1344 commandPacket.setNextValueAsFieldID(event.mods[i].fieldID); 1345 break; 1346 } 1347 case EventMod.ModKind.Step: { 1348 // Case Step 1349 commandPacket.setNextValueAsThreadID(event.mods[i].thread); 1350 commandPacket.setNextValueAsInt(event.mods[i].size); 1351 commandPacket.setNextValueAsInt(event.mods[i].depth); 1352 break; 1353 } 1354 case EventMod.ModKind.InstanceOnly: { 1355 // Case InstanceOnly 1356 commandPacket.setNextValueAsObjectID(event.mods[i].instance); 1357 break; 1358 } 1359 case EventMod.ModKind.SourceNameMatch: { 1360 // Case SourceNameMatch 1361 commandPacket.setNextValueAsString(event.mods[i].sourceNamePattern); 1362 } 1363 } 1364 } 1365 1366 // Send packet 1367 return checkReply(performCommand(commandPacket)); 1368 } 1369 1370 /** 1371 * Gets method reference by signature. 1372 * 1373 * @param classReferenceTypeID 1374 * class referenceTypeID. 1375 * @return ReplyPacket for corresponding command 1376 */ getMethods(long classReferenceTypeID)1377 public ReplyPacket getMethods(long classReferenceTypeID) { 1378 // Create new command packet 1379 CommandPacket commandPacket = new CommandPacket(); 1380 1381 // Set command. "5" - is ID of Methods command in ReferenceType Command 1382 // Set 1383 commandPacket 1384 .setCommand(JDWPCommands.ReferenceTypeCommandSet.MethodsCommand); 1385 1386 // Set command set. "2" - is ID of ReferenceType Command Set 1387 commandPacket 1388 .setCommandSet(JDWPCommands.ReferenceTypeCommandSet.CommandSetID); 1389 1390 // Set outgoing data 1391 // Set referenceTypeID 1392 commandPacket.setNextValueAsObjectID(classReferenceTypeID); 1393 1394 // Send packet 1395 return checkReply(performCommand(commandPacket)); 1396 } 1397 1398 /** 1399 * Gets class reference by signature. 1400 * 1401 * @param classSignature 1402 * class signature. 1403 * @return ReplyPacket for corresponding command 1404 */ getClassBySignature(String classSignature)1405 public ReplyPacket getClassBySignature(String classSignature) { 1406 CommandPacket commandPacket = new CommandPacket( 1407 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 1408 JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand); 1409 commandPacket.setNextValueAsString(classSignature); 1410 return checkReply(performCommand(commandPacket)); 1411 } 1412 1413 /** 1414 * Gets class fields by class referenceTypeID. 1415 * 1416 * @param referenceTypeID 1417 * class referenceTypeID. 1418 * @return ReplyPacket for corresponding command 1419 */ getFieldsInClass(long referenceTypeID)1420 public ReplyPacket getFieldsInClass(long referenceTypeID) { 1421 CommandPacket commandPacket = new CommandPacket( 1422 JDWPCommands.ReferenceTypeCommandSet.CommandSetID, 1423 JDWPCommands.ReferenceTypeCommandSet.FieldsCommand); 1424 commandPacket.setNextValueAsReferenceTypeID(referenceTypeID); 1425 return checkReply(performCommand(commandPacket)); 1426 } 1427 1428 /** 1429 * Sets exception event request for given exception class signature. 1430 * 1431 * @param exceptionSignature 1432 * exception signature. 1433 * @param caught 1434 * is exception caught 1435 * @param uncaught 1436 * is exception uncaught 1437 * @return ReplyPacket for corresponding command 1438 */ setException(String exceptionSignature, boolean caught, boolean uncaught)1439 public ReplyPacket setException(String exceptionSignature, boolean caught, 1440 boolean uncaught) { 1441 // Request referenceTypeID for exception 1442 long typeID = getClassID(exceptionSignature); 1443 return setException(typeID, caught, uncaught); 1444 } 1445 1446 /** 1447 * Sets exception event request for given exception class ID. 1448 * 1449 * @param exceptionID 1450 * exception referenceTypeID. 1451 * @param caught 1452 * is exception caught 1453 * @param uncaught 1454 * is exception uncaught 1455 * @return ReplyPacket for corresponding command 1456 */ setException(long exceptionID, boolean caught, boolean uncaught)1457 public ReplyPacket setException(long exceptionID, boolean caught, 1458 boolean uncaught) { 1459 // Prepare corresponding event 1460 byte eventKind = JDWPConstants.EventKind.EXCEPTION; 1461 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1462 EventMod[] mods = new EventMod[1]; 1463 mods[0] = new EventMod(); 1464 mods[0].modKind = EventMod.ModKind.ExceptionOnly; 1465 mods[0].caught = caught; 1466 mods[0].uncaught = uncaught; 1467 mods[0].exceptionOrNull = exceptionID; 1468 Event event = new Event(eventKind, suspendPolicy, mods); 1469 1470 return setEvent(event); 1471 } 1472 1473 /** 1474 * Sets exception event request for given exception class signature. 1475 * 1476 * @param exceptionSignature 1477 * exception signature. 1478 * @param caught 1479 * is exception caught 1480 * @param uncaught 1481 * is exception uncaught 1482 * @param count 1483 * Limit the requested event to be reported at most once after a 1484 * given number of occurrences 1485 * @return ReplyPacket for corresponding command 1486 */ setCountableException(String exceptionSignature, boolean caught, boolean uncaught, int count)1487 public ReplyPacket setCountableException(String exceptionSignature, 1488 boolean caught, boolean uncaught, int count) { 1489 // Request referenceTypeID for exception 1490 long exceptionID = getClassID(exceptionSignature); 1491 byte eventKind = JDWPConstants.EventKind.EXCEPTION; 1492 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1493 EventMod[] mods = new EventMod[2]; 1494 mods[0] = new EventMod(); 1495 mods[0].modKind = EventMod.ModKind.ExceptionOnly; 1496 mods[0].caught = caught; 1497 mods[0].uncaught = uncaught; 1498 mods[0].exceptionOrNull = exceptionID; 1499 1500 mods[1] = new EventMod(); 1501 mods[1].modKind = EventMod.ModKind.Count; 1502 mods[1].count = count; 1503 Event event = new Event(eventKind, suspendPolicy, mods); 1504 1505 return setEvent(event); 1506 } 1507 1508 /** 1509 * Sets METHOD_ENTRY event request for specified class name pattern. 1510 * 1511 * @param classRegexp 1512 * class name pattern or null for no pattern 1513 * 1514 * @return ReplyPacket for corresponding command 1515 */ setMethodEntry(String classRegexp)1516 public ReplyPacket setMethodEntry(String classRegexp) { 1517 // Prepare corresponding event 1518 byte eventKind = JDWPConstants.EventKind.METHOD_ENTRY; 1519 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1520 EventMod[] mods = null; 1521 if (classRegexp == null) { 1522 mods = new EventMod[0]; 1523 } else { 1524 mods = new EventMod[1]; 1525 mods[0] = new EventMod(); 1526 mods[0].modKind = EventMod.ModKind.ClassMatch; 1527 mods[0].classPattern = classRegexp; 1528 } 1529 Event event = new Event(eventKind, suspendPolicy, mods); 1530 1531 return setEvent(event); 1532 } 1533 1534 /** 1535 * Sets METHOD_ENTRY event request for specified class name pattern. 1536 * 1537 * @param classRegexp 1538 * class name pattern or null for no pattern 1539 * @param count 1540 * Limit the requested event to be reported at most once after a 1541 * given number of occurrences 1542 * @return ReplyPacket for corresponding command 1543 */ setCountableMethodEntry(String classRegexp, int count)1544 public ReplyPacket setCountableMethodEntry(String classRegexp, int count) { 1545 byte eventKind = JDWPConstants.EventKind.METHOD_ENTRY; 1546 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1547 EventMod[] mods = null; 1548 if (classRegexp == null) { 1549 mods = new EventMod[] { new EventMod() }; 1550 mods[0].modKind = EventMod.ModKind.Count; 1551 mods[0].count = count; 1552 } else { 1553 mods = new EventMod[2]; 1554 mods[0] = new EventMod(); 1555 mods[0].modKind = EventMod.ModKind.ClassMatch; 1556 mods[0].classPattern = classRegexp; 1557 1558 mods[1] = new EventMod(); 1559 mods[1].modKind = EventMod.ModKind.Count; 1560 mods[1].count = count; 1561 } 1562 Event event = new Event(eventKind, suspendPolicy, mods); 1563 1564 return setEvent(event); 1565 } 1566 1567 /** 1568 * Sets METHOD_EXIT event request for specified class name pattern. 1569 * 1570 * @param classRegexp 1571 * class name pattern or null for no pattern 1572 * 1573 * @return ReplyPacket for corresponding command 1574 */ setMethodExit(String classRegexp)1575 public ReplyPacket setMethodExit(String classRegexp) { 1576 // Prepare corresponding event 1577 byte eventKind = JDWPConstants.EventKind.METHOD_EXIT; 1578 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1579 EventMod[] mods = null; 1580 if (classRegexp == null) { 1581 mods = new EventMod[0]; 1582 } else { 1583 mods = new EventMod[1]; 1584 mods[0] = new EventMod(); 1585 mods[0].modKind = EventMod.ModKind.ClassMatch; 1586 mods[0].classPattern = classRegexp; 1587 } 1588 Event event = new Event(eventKind, suspendPolicy, mods); 1589 1590 return setEvent(event); 1591 } 1592 1593 /** 1594 * Sets METHOD_EXIT_WITH_RETURN_VALUE event request for specified class name pattern. 1595 * 1596 * @param classRegexp 1597 * class name pattern or null for no pattern 1598 * 1599 * @return ReplyPacket for corresponding command 1600 */ setMethodExitWithReturnValue(String classRegexp)1601 public ReplyPacket setMethodExitWithReturnValue(String classRegexp) { 1602 // Prepare corresponding event 1603 byte eventKind = JDWPConstants.EventKind.METHOD_EXIT_WITH_RETURN_VALUE; 1604 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1605 EventMod[] mods = null; 1606 if (classRegexp == null) { 1607 mods = new EventMod[0]; 1608 } else { 1609 mods = new EventMod[1]; 1610 mods[0] = new EventMod(); 1611 mods[0].modKind = EventMod.ModKind.ClassMatch; 1612 mods[0].classPattern = classRegexp; 1613 } 1614 Event event = new Event(eventKind, suspendPolicy, mods); 1615 1616 return setEvent(event); 1617 } 1618 1619 /** 1620 * Sets METHOD_EXIT event request for specified class name pattern. 1621 * 1622 * @param classRegexp 1623 * classRegexp class name pattern or null for no pattern 1624 * @param count 1625 * Limit the requested event to be reported at most once after a 1626 * given number of occurrences 1627 * @return ReplyPacket for corresponding command 1628 */ setCountableMethodExit(String classRegexp, int count)1629 public ReplyPacket setCountableMethodExit(String classRegexp, int count) { 1630 byte eventKind = JDWPConstants.EventKind.METHOD_EXIT; 1631 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1632 EventMod[] mods = null; 1633 if (classRegexp == null) { 1634 mods = new EventMod[] { new EventMod() }; 1635 mods[0].modKind = EventMod.ModKind.Count; 1636 mods[0].count = count; 1637 } else { 1638 mods = new EventMod[2]; 1639 mods[0] = new EventMod(); 1640 mods[0].modKind = EventMod.ModKind.ClassMatch; 1641 mods[0].classPattern = classRegexp; 1642 1643 mods[1] = new EventMod(); 1644 mods[1].modKind = EventMod.ModKind.Count; 1645 mods[1].count = count; 1646 } 1647 Event event = new Event(eventKind, suspendPolicy, mods); 1648 1649 return setEvent(event); 1650 1651 } 1652 1653 /** 1654 * Sets field access event request for specified class signature and field 1655 * name. 1656 * 1657 * @param classTypeTag 1658 * class Type Tag (class/interface/array) 1659 * @param classSignature 1660 * class signature 1661 * @param fieldName 1662 * field name 1663 * @return ReplyPacket if breakpoint is set 1664 * @throws ReplyErrorCodeException 1665 */ setFieldAccess(String classSignature, byte classTypeTag, String fieldName)1666 public ReplyPacket setFieldAccess(String classSignature, byte classTypeTag, 1667 String fieldName) throws ReplyErrorCodeException { 1668 ReplyPacket request = null; 1669 long typeID = -1; 1670 long fieldID = -1; 1671 1672 // Request referenceTypeID for class 1673 typeID = getClassID(classSignature); 1674 1675 // Request fields in class 1676 request = getFieldsInClass(typeID); 1677 1678 // Get fieldID from received packet 1679 fieldID = getFieldID(request, fieldName); 1680 1681 // Prepare corresponding event 1682 byte eventKind = JDWPConstants.EventKind.FIELD_ACCESS; 1683 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1684 // EventMod[] mods = new EventMod[1]; 1685 EventMod[] mods = new EventMod[] { new EventMod() }; 1686 mods[0].fieldID = fieldID; 1687 mods[0].declaring = typeID; 1688 mods[0].modKind = EventMod.ModKind.FieldOnly; 1689 Event event = new Event(eventKind, suspendPolicy, mods); 1690 1691 // Set exception 1692 return setEvent(event); 1693 } 1694 1695 /** 1696 * Sets field modification event request for specified class signature and 1697 * field name. 1698 * 1699 * @param classTypeTag 1700 * class Type Tag (class/interface/array) 1701 * @param classSignature 1702 * class signature 1703 * @param fieldName 1704 * field name 1705 * @return ReplyPacket for corresponding command 1706 * @throws ReplyErrorCodeException 1707 */ setFieldModification(String classSignature, byte classTypeTag, String fieldName)1708 public ReplyPacket setFieldModification(String classSignature, 1709 byte classTypeTag, String fieldName) throws ReplyErrorCodeException { 1710 ReplyPacket request = null; 1711 long typeID = -1; 1712 long fieldID = -1; 1713 1714 // Request referenceTypeID for class 1715 typeID = getClassID(classSignature); 1716 1717 // Request fields in class 1718 request = getFieldsInClass(typeID); 1719 1720 // Get fieldID from received packet 1721 fieldID = getFieldID(request, fieldName); 1722 1723 // Prepare corresponding event 1724 byte eventKind = JDWPConstants.EventKind.FIELD_MODIFICATION; 1725 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1726 // EventMod[] mods = new EventMod[1]; 1727 EventMod[] mods = new EventMod[] { new EventMod() }; 1728 mods[0].fieldID = fieldID; 1729 mods[0].declaring = typeID; 1730 mods[0].modKind = EventMod.ModKind.FieldOnly; 1731 Event event = new Event(eventKind, suspendPolicy, mods); 1732 1733 // Set event 1734 return setEvent(event); 1735 } 1736 1737 /** 1738 * Sets step event request for given thread name. 1739 * 1740 * @param threadName 1741 * thread name 1742 * @param stepSize 1743 * @param stepDepth 1744 * @return ReplyPacket for corresponding command 1745 */ setStep(String threadName, int stepSize, int stepDepth)1746 public ReplyPacket setStep(String threadName, int stepSize, int stepDepth) { 1747 long typeID = -1; 1748 1749 // Request referenceTypeID for class 1750 typeID = getThreadID(threadName); 1751 1752 // Prepare corresponding event 1753 byte eventKind = JDWPConstants.EventKind.SINGLE_STEP; 1754 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1755 // EventMod[] mods = new EventMod[1]; 1756 EventMod[] mods = new EventMod[] { new EventMod() }; 1757 mods[0].thread = typeID; 1758 mods[0].modKind = EventMod.ModKind.Step; 1759 mods[0].size = stepSize; 1760 mods[0].depth = stepDepth; 1761 Event event = new Event(eventKind, suspendPolicy, mods); 1762 1763 // Set event 1764 return setEvent(event); 1765 } 1766 1767 /** 1768 * Sets SINGLE_STEP event request for classes whose name does not match the 1769 * given restricted regular expression 1770 * 1771 * @param classRegexp 1772 * Disallowed class patterns. Matches are limited to exact 1773 * matches of the given class pattern and matches of patterns 1774 * that begin or end with '*'; for example, "*.Foo" or "java.*". 1775 * @param stepSize 1776 * @param stepDepth 1777 * @return ReplyPacket for setting request. 1778 */ setStep(String[] classRegexp, long threadID, int stepSize, int stepDepth)1779 public ReplyPacket setStep(String[] classRegexp, long threadID, 1780 int stepSize, int stepDepth) { 1781 // Prepare corresponding event 1782 byte eventKind = JDWPConstants.EventKind.SINGLE_STEP; 1783 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1784 int modsSize = classRegexp.length + 1; 1785 EventMod[] mods = new EventMod[modsSize]; 1786 for (int i = 0; i < classRegexp.length; i++) { 1787 mods[i] = new EventMod(); 1788 mods[i].classPattern = classRegexp[i]; 1789 mods[i].modKind = EventMod.ModKind.ClassExclude; 1790 } 1791 1792 int index = modsSize - 1; 1793 mods[index] = new EventMod(); 1794 mods[index].modKind = EventMod.ModKind.Step; 1795 mods[index].thread = threadID; 1796 mods[index].size = stepSize; 1797 mods[index].depth = stepDepth; 1798 1799 Event event = new Event(eventKind, suspendPolicy, mods); 1800 1801 // Set event 1802 return setEvent(event); 1803 } 1804 1805 /** 1806 * Sets THREAD_START event request. 1807 * 1808 * @return ReplyPacket for corresponding command 1809 */ setThreadStart()1810 public ReplyPacket setThreadStart() { 1811 // Prepare corresponding event 1812 byte eventKind = JDWPConstants.EventKind.THREAD_START; 1813 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1814 EventMod[] mods = new EventMod[0]; 1815 Event event = new Event(eventKind, suspendPolicy, mods); 1816 1817 return setEvent(event); 1818 } 1819 1820 /** 1821 * Sets THREAD_END event request. 1822 * 1823 * @return ReplyPacket for corresponding command 1824 */ setThreadEnd()1825 public ReplyPacket setThreadEnd() { 1826 // Prepare corresponding event 1827 byte eventKind = JDWPConstants.EventKind.THREAD_END; 1828 byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; 1829 EventMod[] mods = new EventMod[0]; 1830 Event event = new Event(eventKind, suspendPolicy, mods); 1831 1832 return setEvent(event); 1833 } 1834 1835 /** 1836 * Clear an event request for specified request ID. 1837 * 1838 * @param eventKind 1839 * event type to clear 1840 * @param requestID 1841 * request ID to clear 1842 * @return ReplyPacket for corresponding command 1843 */ clearEvent(byte eventKind, int requestID)1844 public ReplyPacket clearEvent(byte eventKind, int requestID) { 1845 // Create new command packet 1846 CommandPacket commandPacket = new CommandPacket(); 1847 1848 // Set command. "2" - is ID of Clear command in EventRequest Command Set 1849 commandPacket 1850 .setCommand(JDWPCommands.EventRequestCommandSet.ClearCommand); 1851 1852 // Set command set. "15" - is ID of EventRequest Command Set 1853 commandPacket 1854 .setCommandSet(JDWPCommands.EventRequestCommandSet.CommandSetID); 1855 1856 // Set outgoing data 1857 // Set event type to clear 1858 commandPacket.setNextValueAsByte(eventKind); 1859 1860 // Set ID of request to clear 1861 commandPacket.setNextValueAsInt(requestID); 1862 1863 // Send packet 1864 return checkReply(performCommand(commandPacket)); 1865 } 1866 1867 /** 1868 * Sends CommandPacket to debuggee VM and waits for ReplyPacket using 1869 * default timeout. All thrown exceptions are wrapped into 1870 * TestErrorException. Consider using checkReply() for checking error code 1871 * in reply packet. 1872 * 1873 * @param command 1874 * Command packet to be sent 1875 * @return received ReplyPacket 1876 */ performCommand(CommandPacket command)1877 public ReplyPacket performCommand(CommandPacket command) 1878 throws TestErrorException { 1879 ReplyPacket replyPacket = null; 1880 try { 1881 replyPacket = packetDispatcher.performCommand(command); 1882 } catch (IOException e) { 1883 throw new TestErrorException(e); 1884 } catch (InterruptedException e) { 1885 throw new TestErrorException(e); 1886 } 1887 1888 return replyPacket; 1889 } 1890 1891 /** 1892 * Sends CommandPacket to debuggee VM and waits for ReplyPacket using 1893 * specified timeout. 1894 * 1895 * @param command 1896 * Command packet to be sent 1897 * @param timeout 1898 * Timeout in milliseconds for waiting reply packet 1899 * @return received ReplyPacket 1900 * @throws InterruptedException 1901 * @throws IOException 1902 * @throws TimeoutException 1903 */ performCommand(CommandPacket command, long timeout)1904 public ReplyPacket performCommand(CommandPacket command, long timeout) 1905 throws IOException, InterruptedException, TimeoutException { 1906 1907 return packetDispatcher.performCommand(command, timeout); 1908 } 1909 1910 /** 1911 * Sends CommandPacket to debuggee VM without waiting for the reply. This 1912 * method is intended for special cases when there is need to divide 1913 * command's performing into two actions: command's sending and receiving 1914 * reply (e.g. for asynchronous JDWP commands' testing). After this method 1915 * the 'receiveReply()' method must be used latter for receiving reply for 1916 * sent command. It is NOT recommended to use this method for usual cases - 1917 * 'performCommand()' method must be used. 1918 * 1919 * @param command 1920 * Command packet to be sent 1921 * @return command ID of sent command 1922 * @throws IOException 1923 * if any connection error occurred 1924 */ sendCommand(CommandPacket command)1925 public int sendCommand(CommandPacket command) throws IOException { 1926 return packetDispatcher.sendCommand(command); 1927 } 1928 1929 /** 1930 * Waits for reply for command which was sent before by 'sendCommand()' 1931 * method. Default timeout is used as time limit for waiting. This method 1932 * (jointly with 'sendCommand()') is intended for special cases when there 1933 * is need to divide command's performing into two actions: command's 1934 * sending and receiving reply (e.g. for asynchronous JDWP commands' 1935 * testing). It is NOT recommended to use 'sendCommand()- receiveReply()' 1936 * pair for usual cases - 'performCommand()' method must be used. 1937 * 1938 * @param commandId 1939 * Command ID of sent before command, reply from which is 1940 * expected to be received 1941 * @return received ReplyPacket 1942 * @throws IOException 1943 * if any connection error occurred 1944 * @throws InterruptedException 1945 * if reply packet's waiting was interrupted 1946 * @throws TimeoutException 1947 * if timeout exceeded 1948 */ receiveReply(int commandId)1949 public ReplyPacket receiveReply(int commandId) throws InterruptedException, 1950 IOException, TimeoutException { 1951 return packetDispatcher.receiveReply(commandId, config.getTimeout()); 1952 } 1953 1954 /** 1955 * Waits for reply for command which was sent before by 'sendCommand()' 1956 * method. Specified timeout is used as time limit for waiting. This method 1957 * (jointly with 'sendCommand()') is intended for special cases when there 1958 * is need to divide command's performing into two actions: command's 1959 * sending and receiving reply (e.g. for asynchronous JDWP commands' 1960 * testing). It is NOT recommended to use 'sendCommand()- receiveReply()' 1961 * pair for usual cases - 'performCommand()' method must be used. 1962 * 1963 * @param commandId 1964 * Command ID of sent before command, reply from which is 1965 * expected to be received 1966 * @param timeout 1967 * Specified timeout in milliseconds to wait for reply 1968 * @return received ReplyPacket 1969 * @throws IOException 1970 * if any connection error occurred 1971 * @throws InterruptedException 1972 * if reply packet's waiting was interrupted 1973 * @throws TimeoutException 1974 * if timeout exceeded 1975 */ receiveReply(int commandId, long timeout)1976 public ReplyPacket receiveReply(int commandId, long timeout) 1977 throws InterruptedException, IOException, TimeoutException { 1978 return packetDispatcher.receiveReply(commandId, timeout); 1979 } 1980 1981 /** 1982 * Waits for EventPacket using default timeout. All thrown exceptions are 1983 * wrapped into TestErrorException. 1984 * 1985 * @return received EventPacket 1986 */ receiveEvent()1987 public EventPacket receiveEvent() throws TestErrorException { 1988 try { 1989 return receiveEvent(config.getTimeout()); 1990 } catch (IOException e) { 1991 throw new TestErrorException(e); 1992 } catch (InterruptedException e) { 1993 throw new TestErrorException(e); 1994 } 1995 } 1996 1997 /** 1998 * Waits for EventPacket using specified timeout. 1999 * 2000 * @param timeout 2001 * Timeout in milliseconds to wait for event 2002 * @return received EventPacket 2003 * @throws IOException 2004 * @throws InterruptedException 2005 * @throws TimeoutException 2006 */ receiveEvent(long timeout)2007 public EventPacket receiveEvent(long timeout) throws IOException, 2008 InterruptedException, TimeoutException { 2009 2010 return packetDispatcher.receiveEvent(timeout); 2011 } 2012 2013 /** 2014 * Waits for expected event kind using default timeout. Throws 2015 * TestErrorException if received event is not of expected kind or not a 2016 * single event in the received event set. 2017 * 2018 * @param eventKind 2019 * Type of expected event - 2020 * @see JDWPConstants.EventKind 2021 * @return received EventPacket 2022 */ receiveCertainEvent(byte eventKind)2023 public EventPacket receiveCertainEvent(byte eventKind) 2024 throws TestErrorException { 2025 2026 EventPacket eventPacket = receiveEvent(); 2027 ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(eventPacket); 2028 2029 if (parsedEvents.length == 1 2030 && parsedEvents[0].getEventKind() == eventKind) 2031 return eventPacket; 2032 2033 switch (parsedEvents.length) { 2034 case (0): 2035 throw new TestErrorException( 2036 "Unexpected event received: zero length"); 2037 case (1): 2038 throw new TestErrorException("Unexpected event received: " 2039 + parsedEvents[0].getEventKind()); 2040 default: 2041 throw new TestErrorException( 2042 "Unexpected event received: Event was grouped in a composite event"); 2043 } 2044 } 2045 2046 /** 2047 * Returns JDWP connection channel used by this VmMirror. 2048 * 2049 * @return connection channel 2050 */ getConnection()2051 public TransportWrapper getConnection() { 2052 return connection; 2053 } 2054 2055 /** 2056 * Sets established connection channel to be used with this VmMirror and 2057 * starts reading packets. 2058 * 2059 * @param connection 2060 * connection channel to be set 2061 */ setConnection(TransportWrapper connection)2062 public void setConnection(TransportWrapper connection) { 2063 this.connection = connection; 2064 packetDispatcher = new PacketDispatcher(connection, config, logWriter); 2065 } 2066 2067 /** 2068 * Closes connection channel used with this VmMirror and stops reading 2069 * packets. 2070 * 2071 */ closeConnection()2072 public void closeConnection() throws IOException { 2073 if (connection != null && connection.isOpen()) 2074 connection.close(); 2075 2076 // wait for packetDispatcher is closed 2077 if (packetDispatcher != null) { 2078 try { 2079 packetDispatcher.join(); 2080 } catch (InterruptedException e) { 2081 // do nothing but print a stack trace 2082 e.printStackTrace(); 2083 } 2084 } 2085 } 2086 2087 /** 2088 * Returns the count of frames on this thread's stack 2089 * 2090 * @param threadID 2091 * The thread object ID. 2092 * @return The count of frames on this thread's stack 2093 */ getFrameCount(long threadID)2094 public final int getFrameCount(long threadID) { 2095 CommandPacket command = new CommandPacket( 2096 JDWPCommands.ThreadReferenceCommandSet.CommandSetID, 2097 JDWPCommands.ThreadReferenceCommandSet.FrameCountCommand); 2098 command.setNextValueAsThreadID(threadID); 2099 ReplyPacket reply = checkReply(performCommand(command)); 2100 return reply.getNextValueAsInt(); 2101 } 2102 2103 /** 2104 * Returns a list containing all frames of a certain thread 2105 * 2106 * @param threadID 2107 * ID of the thread 2108 * @return A list of frames 2109 */ getAllThreadFrames(long threadID)2110 public final List getAllThreadFrames(long threadID) { 2111 if (!isThreadSuspended(threadID)) { 2112 return new ArrayList(0); 2113 } 2114 2115 ReplyPacket reply = getThreadFrames(threadID, 0, -1); 2116 int framesCount = reply.getNextValueAsInt(); 2117 if (framesCount == 0) { 2118 return new ArrayList(0); 2119 } 2120 2121 ArrayList<Frame> frames = new ArrayList<Frame>(framesCount); 2122 for (int i = 0; i < framesCount; i++) { 2123 Frame frame = new Frame(); 2124 frame.setThreadID(threadID); 2125 frame.setID(reply.getNextValueAsFrameID()); 2126 frame.setLocation(reply.getNextValueAsLocation()); 2127 frames.add(frame); 2128 } 2129 2130 return frames; 2131 } 2132 2133 /** 2134 * Returns a set of frames of a certain suspended thread 2135 * 2136 * @param threadID 2137 * ID of the thread whose frames to obtain 2138 * @param startIndex 2139 * The index of the first frame to retrieve. 2140 * @param length 2141 * The count of frames to retrieve (-1 means all remaining). 2142 * @return ReplyPacket for corresponding command 2143 */ getThreadFrames(long threadID, int startIndex, int length)2144 public final ReplyPacket getThreadFrames(long threadID, int startIndex, 2145 int length) { 2146 CommandPacket command = new CommandPacket( 2147 JDWPCommands.ThreadReferenceCommandSet.CommandSetID, 2148 JDWPCommands.ThreadReferenceCommandSet.FramesCommand); 2149 command.setNextValueAsThreadID(threadID); 2150 command.setNextValueAsInt(startIndex); // start frame's index 2151 command.setNextValueAsInt(length); // get all remaining frames; 2152 return checkReply(performCommand(command)); 2153 } 2154 2155 /** 2156 * Returns variable information for the method 2157 * 2158 * @param classID 2159 * The class ID 2160 * @param methodID 2161 * The method ID 2162 * @return A list containing all variables (arguments and locals) declared 2163 * within the method. 2164 */ getVariableTable(long classID, long methodID)2165 public final List getVariableTable(long classID, long methodID) { 2166 CommandPacket command = new CommandPacket( 2167 JDWPCommands.MethodCommandSet.CommandSetID, 2168 JDWPCommands.MethodCommandSet.VariableTableCommand); 2169 command.setNextValueAsReferenceTypeID(classID); 2170 command.setNextValueAsMethodID(methodID); 2171 // ReplyPacket reply = 2172 // debuggeeWrapper.vmMirror.checkReply(debuggeeWrapper.vmMirror.performCommand(command)); 2173 ReplyPacket reply = performCommand(command); 2174 if (reply.getErrorCode() == JDWPConstants.Error.ABSENT_INFORMATION 2175 || reply.getErrorCode() == JDWPConstants.Error.NATIVE_METHOD) { 2176 return null; 2177 } 2178 2179 checkReply(reply); 2180 2181 reply.getNextValueAsInt(); // argCnt, is not used 2182 int slots = reply.getNextValueAsInt(); 2183 if (slots == 0) { 2184 return null; 2185 } 2186 2187 ArrayList<Variable> vars = new ArrayList<Variable>(slots); 2188 for (int i = 0; i < slots; i++) { 2189 Variable var = new Frame().new Variable(); 2190 var.setCodeIndex(reply.getNextValueAsLong()); 2191 var.setName(reply.getNextValueAsString()); 2192 var.setSignature(reply.getNextValueAsString()); 2193 var.setLength(reply.getNextValueAsInt()); 2194 var.setSlot(reply.getNextValueAsInt()); 2195 vars.add(var); 2196 } 2197 2198 return vars; 2199 } 2200 2201 /** 2202 * Returns values of local variables in a given frame 2203 * 2204 * @param frame 2205 * Frame whose variables to get 2206 * @return An array of Value objects 2207 */ getFrameValues(Frame frame)2208 public final Value[] getFrameValues(Frame frame) { 2209 CommandPacket command = new CommandPacket( 2210 JDWPCommands.StackFrameCommandSet.CommandSetID, 2211 JDWPCommands.StackFrameCommandSet.GetValuesCommand); 2212 command.setNextValueAsThreadID(frame.getThreadID()); 2213 command.setNextValueAsFrameID(frame.getID()); 2214 int slots = frame.getVars().size(); 2215 command.setNextValueAsInt(slots); 2216 Iterator it = frame.getVars().iterator(); 2217 while (it.hasNext()) { 2218 Frame.Variable var = (Frame.Variable) it.next(); 2219 command.setNextValueAsInt(var.getSlot()); 2220 command.setNextValueAsByte(var.getTag()); 2221 } 2222 2223 ReplyPacket reply = checkReply(performCommand(command)); 2224 reply.getNextValueAsInt(); // number of values , is not used 2225 Value[] values = new Value[slots]; 2226 for (int i = 0; i < slots; i++) { 2227 values[i] = reply.getNextValueAsValue(); 2228 } 2229 2230 return values; 2231 } 2232 2233 /** 2234 * Returns the immediate superclass of a class 2235 * 2236 * @param classID 2237 * The class ID whose superclass ID is to get 2238 * @return The superclass ID (null if the class ID for java.lang.Object is 2239 * specified). 2240 */ getSuperclassId(long classID)2241 public final long getSuperclassId(long classID) { 2242 CommandPacket command = new CommandPacket( 2243 JDWPCommands.ClassTypeCommandSet.CommandSetID, 2244 JDWPCommands.ClassTypeCommandSet.SuperclassCommand); 2245 command.setNextValueAsClassID(classID); 2246 ReplyPacket reply = checkReply(performCommand(command)); 2247 return reply.getNextValueAsClassID(); 2248 } 2249 2250 /** 2251 * Returns the runtime type of the object 2252 * 2253 * @param objectID 2254 * The object ID 2255 * @return The runtime reference type. 2256 */ getReferenceType(long objectID)2257 public final long getReferenceType(long objectID) { 2258 CommandPacket command = new CommandPacket( 2259 JDWPCommands.ObjectReferenceCommandSet.CommandSetID, 2260 JDWPCommands.ObjectReferenceCommandSet.ReferenceTypeCommand); 2261 command.setNextValueAsObjectID(objectID); 2262 ReplyPacket reply = checkReply(performCommand(command)); 2263 reply.getNextValueAsByte(); 2264 return reply.getNextValueAsLong(); 2265 } 2266 2267 /** 2268 * Returns the class object corresponding to this type 2269 * 2270 * @param refType 2271 * The reference type ID. 2272 * @return The class object. 2273 */ getClassObjectId(long refType)2274 public final long getClassObjectId(long refType) { 2275 CommandPacket command = new CommandPacket( 2276 JDWPCommands.ReferenceTypeCommandSet.CommandSetID, 2277 JDWPCommands.ReferenceTypeCommandSet.ClassObjectCommand); 2278 command.setNextValueAsReferenceTypeID(refType); 2279 ReplyPacket reply = checkReply(performCommand(command)); 2280 return reply.getNextValueAsObjectID(); 2281 } 2282 2283 /** 2284 * Returns line number information for the method, if present. 2285 * 2286 * @param refType 2287 * The class ID 2288 * @param methodID 2289 * The method ID 2290 * @return ReplyPacket for corresponding command. 2291 */ getLineTable(long refType, long methodID)2292 public final ReplyPacket getLineTable(long refType, long methodID) { 2293 CommandPacket command = new CommandPacket( 2294 JDWPCommands.MethodCommandSet.CommandSetID, 2295 JDWPCommands.MethodCommandSet.LineTableCommand); 2296 command.setNextValueAsReferenceTypeID(refType); 2297 command.setNextValueAsMethodID(methodID); 2298 // ReplyPacket reply = 2299 // debuggeeWrapper.vmMirror.checkReply(debuggeeWrapper.vmMirror.performCommand(command)); 2300 // it is impossible to obtain line table information from native 2301 // methods, so reply checking is not performed 2302 ReplyPacket reply = performCommand(command); 2303 if (reply.getErrorCode() != JDWPConstants.Error.NONE) { 2304 if (reply.getErrorCode() == JDWPConstants.Error.NATIVE_METHOD) { 2305 return reply; 2306 } 2307 } 2308 2309 return checkReply(reply); 2310 } 2311 2312 /** 2313 * Returns the value of one or more instance fields. 2314 * 2315 * @param objectID 2316 * The object ID 2317 * @param fieldIDs 2318 * IDs of fields to get 2319 * @return An array of Value objects representing each field's value 2320 */ getObjectReferenceValues(long objectID, long[] fieldIDs)2321 public final Value[] getObjectReferenceValues(long objectID, long[] fieldIDs) { 2322 int fieldsCount = fieldIDs.length; 2323 if (fieldsCount == 0) { 2324 return null; 2325 } 2326 2327 CommandPacket command = new CommandPacket( 2328 JDWPCommands.ObjectReferenceCommandSet.CommandSetID, 2329 JDWPCommands.ObjectReferenceCommandSet.GetValuesCommand); 2330 command.setNextValueAsReferenceTypeID(objectID); 2331 command.setNextValueAsInt(fieldsCount); 2332 for (int i = 0; i < fieldsCount; i++) { 2333 command.setNextValueAsFieldID(fieldIDs[i]); 2334 } 2335 2336 ReplyPacket reply = checkReply(performCommand(command)); 2337 reply.getNextValueAsInt(); // fields returned, is not used 2338 Value[] values = new Value[fieldsCount]; 2339 for (int i = 0; i < fieldsCount; i++) { 2340 values[i] = reply.getNextValueAsValue(); 2341 } 2342 2343 return values; 2344 } 2345 2346 /** 2347 * Returns the value of one or more static fields of the reference type 2348 * 2349 * @param refTypeID 2350 * The reference type ID. 2351 * @param fieldIDs 2352 * IDs of fields to get 2353 * @return An array of Value objects representing each field's value 2354 */ getReferenceTypeValues(long refTypeID, long[] fieldIDs)2355 public final Value[] getReferenceTypeValues(long refTypeID, long[] fieldIDs) { 2356 int fieldsCount = fieldIDs.length; 2357 if (fieldsCount == 0) { 2358 return null; 2359 } 2360 2361 CommandPacket command = new CommandPacket( 2362 JDWPCommands.ReferenceTypeCommandSet.CommandSetID, 2363 JDWPCommands.ReferenceTypeCommandSet.GetValuesCommand); 2364 command.setNextValueAsReferenceTypeID(refTypeID); 2365 command.setNextValueAsInt(fieldsCount); 2366 for (int i = 0; i < fieldsCount; i++) { 2367 command.setNextValueAsFieldID(fieldIDs[i]); 2368 } 2369 2370 ReplyPacket reply = checkReply(performCommand(command)); 2371 reply.getNextValueAsInt(); // fields returned, is not used 2372 Value[] values = new Value[fieldsCount]; 2373 for (int i = 0; i < fieldsCount; i++) { 2374 values[i] = reply.getNextValueAsValue(); 2375 } 2376 2377 return values; 2378 } 2379 2380 /** 2381 * Returns the value of one static field of the reference type 2382 * 2383 * @param refTypeID 2384 * The reference type ID. 2385 * @param fieldID 2386 * ID of field to get 2387 * @return A Value object representing the field's value 2388 */ getReferenceTypeValue(long refTypeID, long fieldID)2389 public final Value getReferenceTypeValue(long refTypeID, long fieldID) { 2390 Value[] values = getReferenceTypeValues(refTypeID, new long[]{fieldID}); 2391 return values[0]; 2392 } 2393 2394 /** 2395 * Returns the value of the 'this' reference for this frame 2396 * 2397 * @param threadID 2398 * The frame's thread ID 2399 * @param frameID 2400 * The frame ID. 2401 * @return The 'this' object ID for this frame. 2402 */ getThisObject(long threadID, long frameID)2403 public final long getThisObject(long threadID, long frameID) { 2404 CommandPacket command = new CommandPacket( 2405 JDWPCommands.StackFrameCommandSet.CommandSetID, 2406 JDWPCommands.StackFrameCommandSet.ThisObjectCommand); 2407 command.setNextValueAsThreadID(threadID); 2408 command.setNextValueAsFrameID(frameID); 2409 ReplyPacket reply = checkReply(performCommand(command)); 2410 TaggedObject taggedObject = reply.getNextValueAsTaggedObject(); 2411 return taggedObject.objectID; 2412 } 2413 2414 /** 2415 * Returns information for each field in a reference type including 2416 * inherited fields 2417 * 2418 * @param classID 2419 * The reference type ID 2420 * @return A list of Field objects representing each field of the class 2421 */ getAllFields(long classID)2422 public final List getAllFields(long classID) { 2423 ArrayList<Field> fields = new ArrayList<Field>(0); 2424 2425 long superID = getSuperclassId(classID); 2426 if (superID != 0) { 2427 List superClassFields = getAllFields(superID); 2428 for (int i = 0; i < superClassFields.size(); i++) { 2429 fields.add((Field) superClassFields.toArray()[i]); 2430 } 2431 } 2432 2433 ReplyPacket reply = getFieldsInClass(classID); 2434 int fieldsCount = reply.getNextValueAsInt(); 2435 for (int i = 0; i < fieldsCount; i++) { 2436 Field field = new Field(reply.getNextValueAsFieldID(), classID, 2437 reply.getNextValueAsString(), reply.getNextValueAsString(), 2438 reply.getNextValueAsInt()); 2439 fields.add(field); 2440 } 2441 2442 return fields; 2443 } 2444 2445 /** 2446 * Returns the reference type reflected by this class object 2447 * 2448 * @param classObjectID 2449 * The class object ID. 2450 * @return ReplyPacket for corresponding command 2451 */ getReflectedType(long classObjectID)2452 public final ReplyPacket getReflectedType(long classObjectID) { 2453 CommandPacket command = new CommandPacket( 2454 JDWPCommands.ClassObjectReferenceCommandSet.CommandSetID, 2455 JDWPCommands.ClassObjectReferenceCommandSet.ReflectedTypeCommand); 2456 command.setNextValueAsClassObjectID(classObjectID); 2457 return checkReply(performCommand(command)); 2458 } 2459 2460 /** 2461 * Returns the JNI signature of a reference type. JNI signature formats are 2462 * described in the Java Native Interface Specification 2463 * 2464 * @param refTypeID 2465 * The reference type ID. 2466 * @return The JNI signature for the reference type. 2467 */ getReferenceTypeSignature(long refTypeID)2468 public final String getReferenceTypeSignature(long refTypeID) { 2469 CommandPacket command = new CommandPacket( 2470 JDWPCommands.ReferenceTypeCommandSet.CommandSetID, 2471 JDWPCommands.ReferenceTypeCommandSet.SignatureCommand); 2472 command.setNextValueAsReferenceTypeID(refTypeID); 2473 ReplyPacket reply = checkReply(performCommand(command)); 2474 return reply.getNextValueAsString(); 2475 } 2476 2477 /** 2478 * Returns the thread group that contains a given thread 2479 * 2480 * @param threadID 2481 * The thread object ID. 2482 * @return The thread group ID of this thread. 2483 */ getThreadGroupID(long threadID)2484 public final long getThreadGroupID(long threadID) { 2485 CommandPacket command = new CommandPacket( 2486 JDWPCommands.ThreadReferenceCommandSet.CommandSetID, 2487 JDWPCommands.ThreadReferenceCommandSet.ThreadGroupCommand); 2488 command.setNextValueAsThreadID(threadID); 2489 ReplyPacket reply = checkReply(performCommand(command)); 2490 return reply.getNextValueAsThreadGroupID(); 2491 } 2492 2493 /** 2494 * Checks whether a given thread is suspended or not 2495 * 2496 * @param threadID 2497 * The thread object ID. 2498 * @return True if a given thread is suspended, false otherwise. 2499 */ isThreadSuspended(long threadID)2500 public final boolean isThreadSuspended(long threadID) { 2501 CommandPacket command = new CommandPacket( 2502 JDWPCommands.ThreadReferenceCommandSet.CommandSetID, 2503 JDWPCommands.ThreadReferenceCommandSet.StatusCommand); 2504 command.setNextValueAsThreadID(threadID); 2505 ReplyPacket reply = checkReply(performCommand(command)); 2506 reply.getNextValueAsInt(); // the thread's status; is not used 2507 return reply.getNextValueAsInt() == JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED; 2508 } 2509 2510 /** 2511 * Returns JNI signature of method. 2512 * 2513 * @param classID 2514 * The reference type ID. 2515 * @param methodID 2516 * The method ID. 2517 * @return JNI signature of method. 2518 */ getMethodSignature(long classID, long methodID)2519 public final String getMethodSignature(long classID, long methodID) { 2520 CommandPacket command = new CommandPacket( 2521 JDWPCommands.ReferenceTypeCommandSet.CommandSetID, 2522 JDWPCommands.ReferenceTypeCommandSet.MethodsCommand); 2523 command.setNextValueAsReferenceTypeID(classID); 2524 ReplyPacket reply = checkReply(performCommand(command)); 2525 int methods = reply.getNextValueAsInt(); 2526 String value = null; 2527 for (int i = 0; i < methods; i++) { 2528 long mID = reply.getNextValueAsMethodID(); 2529 reply.getNextValueAsString(); // name of the method; is not used 2530 String methodSign = reply.getNextValueAsString(); 2531 reply.getNextValueAsInt(); 2532 if (mID == methodID) { 2533 value = methodSign; 2534 value = value.replaceAll("/", "."); 2535 int lastRoundBracketIndex = value.lastIndexOf(")"); 2536 value = value.substring(0, lastRoundBracketIndex + 1); 2537 break; 2538 } 2539 } 2540 2541 return value; 2542 } 2543 2544 /** 2545 * Returns the characters contained in the string 2546 * 2547 * @param objectID 2548 * The String object ID. 2549 * @return A string value. 2550 */ getStringValue(long objectID)2551 public final String getStringValue(long objectID) { 2552 CommandPacket command = new CommandPacket( 2553 JDWPCommands.StringReferenceCommandSet.CommandSetID, 2554 JDWPCommands.StringReferenceCommandSet.ValueCommand); 2555 command.setNextValueAsObjectID(objectID); 2556 ReplyPacket reply = checkReply(performCommand(command)); 2557 return reply.getNextValueAsString(); 2558 } 2559 2560 /** 2561 * Returns a range of array components 2562 * 2563 * @param objectID 2564 * The array object ID. 2565 * @return The retrieved values. 2566 */ getArrayValues(long objectID)2567 public Value[] getArrayValues(long objectID) { 2568 CommandPacket command = new CommandPacket( 2569 JDWPCommands.ArrayReferenceCommandSet.CommandSetID, 2570 JDWPCommands.ArrayReferenceCommandSet.LengthCommand); 2571 command.setNextValueAsArrayID(objectID); 2572 ReplyPacket reply = checkReply(performCommand(command)); 2573 int length = reply.getNextValueAsInt(); 2574 2575 if (length == 0) { 2576 return null; 2577 } 2578 2579 command = new CommandPacket( 2580 JDWPCommands.ArrayReferenceCommandSet.CommandSetID, 2581 JDWPCommands.ArrayReferenceCommandSet.GetValuesCommand); 2582 command.setNextValueAsArrayID(objectID); 2583 command.setNextValueAsInt(0); 2584 command.setNextValueAsInt(length); 2585 reply = checkReply(performCommand(command)); 2586 ArrayRegion arrayRegion = reply.getNextValueAsArrayRegion(); 2587 2588 Value[] values = new Value[length]; 2589 for (int i = 0; i < length; i++) { 2590 values[i] = arrayRegion.getValue(i); 2591 } 2592 2593 return values; 2594 } 2595 2596 /** 2597 * Returns a source line number according to a corresponding line code index 2598 * in a method's line table. 2599 * 2600 * @param classID 2601 * The class object ID. 2602 * @param methodID 2603 * The method ID. 2604 * @param codeIndex 2605 * The line code index. 2606 * @return An integer line number. 2607 */ getLineNumber(long classID, long methodID, long codeIndex)2608 public final int getLineNumber(long classID, long methodID, long codeIndex) { 2609 int lineNumber = -1; 2610 ReplyPacket reply = getLineTable(classID, methodID); 2611 if (reply.getErrorCode() != JDWPConstants.Error.NONE) { 2612 return lineNumber; 2613 } 2614 2615 reply.getNextValueAsLong(); // start line index, is not used 2616 reply.getNextValueAsLong(); // end line index, is not used 2617 int lines = reply.getNextValueAsInt(); 2618 for (int i = 0; i < lines; i++) { 2619 long lineCodeIndex = reply.getNextValueAsLong(); 2620 lineNumber = reply.getNextValueAsInt(); 2621 if (lineCodeIndex == codeIndex) { 2622 break; 2623 } 2624 2625 if (lineCodeIndex > codeIndex) { 2626 --lineNumber; 2627 break; 2628 } 2629 } 2630 2631 return lineNumber; 2632 } 2633 2634 /** 2635 * Returns a line code index according to a corresponding line number in a 2636 * method's line table. 2637 * 2638 * @param classID 2639 * The class object ID. 2640 * @param methodID 2641 * The method ID. 2642 * @param lineNumber 2643 * A source line number. 2644 * @return An integer representing the line code index. 2645 */ getLineCodeIndex(long classID, long methodID, int lineNumber)2646 public final long getLineCodeIndex(long classID, long methodID, 2647 int lineNumber) { 2648 ReplyPacket reply = getLineTable(classID, methodID); 2649 if (reply.getErrorCode() != JDWPConstants.Error.NONE) { 2650 return -1L; 2651 } 2652 2653 reply.getNextValueAsLong(); // start line index, is not used 2654 reply.getNextValueAsLong(); // end line index, is not used 2655 int lines = reply.getNextValueAsInt(); 2656 for (int i = 0; i < lines; i++) { 2657 long lineCodeIndex = reply.getNextValueAsLong(); 2658 if (lineNumber == reply.getNextValueAsInt()) { 2659 return lineCodeIndex; 2660 } 2661 } 2662 2663 return -1L; 2664 } 2665 2666 /** 2667 * Returns all variables which are visible within the given frame. 2668 * 2669 * @param frame 2670 * The frame whose visible local variables to retrieve. 2671 * @return A list of Variable objects representing each visible local 2672 * variable within the given frame. 2673 */ getLocalVars(Frame frame)2674 public final List getLocalVars(Frame frame) { 2675 List vars = getVariableTable(frame.getLocation().classID, frame 2676 .getLocation().methodID); 2677 if (vars == null) { 2678 return null; 2679 } 2680 2681 // All variables that are not visible from within current frame must be 2682 // removed from the list 2683 long frameCodeIndex = frame.getLocation().index; 2684 for (int i = 0; i < vars.size(); i++) { 2685 Variable var = (Variable) vars.toArray()[i]; 2686 long varCodeIndex = var.getCodeIndex(); 2687 if (varCodeIndex > frameCodeIndex 2688 || (frameCodeIndex >= varCodeIndex + var.getLength())) { 2689 vars.remove(i); 2690 --i; 2691 continue; 2692 } 2693 } 2694 2695 return vars; 2696 } 2697 2698 /** 2699 * Sets the value of one or more local variables 2700 * 2701 * @param frame 2702 * The frame ID. 2703 * @param vars 2704 * An array of Variable objects whose values to set 2705 * @param values 2706 * An array of Value objects to set 2707 */ setLocalVars(Frame frame, Variable[] vars, Value[] values)2708 public final void setLocalVars(Frame frame, Variable[] vars, Value[] values) { 2709 if (vars.length != values.length) { 2710 throw new TestErrorException( 2711 "Number of variables doesn't correspond to number of their values"); 2712 } 2713 2714 CommandPacket command = new CommandPacket( 2715 JDWPCommands.StackFrameCommandSet.CommandSetID, 2716 JDWPCommands.StackFrameCommandSet.SetValuesCommand); 2717 command.setNextValueAsThreadID(frame.getThreadID()); 2718 command.setNextValueAsFrameID(frame.getID()); 2719 command.setNextValueAsInt(vars.length); 2720 for (int i = 0; i < vars.length; i++) { 2721 command.setNextValueAsInt(vars[i].getSlot()); 2722 command.setNextValueAsValue(values[i]); 2723 } 2724 2725 checkReply(performCommand(command)); 2726 } 2727 2728 /** 2729 * Sets the value of one or more instance fields 2730 * 2731 * @param objectID 2732 * The object ID. 2733 * @param fieldIDs 2734 * An array of fields IDs 2735 * @param values 2736 * An array of Value objects representing each value to set 2737 */ setInstanceFieldsValues(long objectID, long[] fieldIDs, Value[] values)2738 public final void setInstanceFieldsValues(long objectID, long[] fieldIDs, 2739 Value[] values) { 2740 if (fieldIDs.length != values.length) { 2741 throw new TestErrorException( 2742 "Number of fields doesn't correspond to number of their values"); 2743 } 2744 2745 CommandPacket command = new CommandPacket( 2746 JDWPCommands.ObjectReferenceCommandSet.CommandSetID, 2747 JDWPCommands.ObjectReferenceCommandSet.SetValuesCommand); 2748 command.setNextValueAsObjectID(objectID); 2749 command.setNextValueAsInt(fieldIDs.length); 2750 for (int i = 0; i < fieldIDs.length; i++) { 2751 command.setNextValueAsFieldID(fieldIDs[i]); 2752 command.setNextValueAsUntaggedValue(values[i]); 2753 } 2754 2755 checkReply(performCommand(command)); 2756 } 2757 2758 /** 2759 * Sets a range of array components. The specified range must be within the 2760 * bounds of the array. 2761 * 2762 * @param arrayID 2763 * The array object ID. 2764 * @param firstIndex 2765 * The first index to set. 2766 * @param values 2767 * An array of Value objects representing each value to set. 2768 */ setArrayValues(long arrayID, int firstIndex, Value[] values)2769 public final void setArrayValues(long arrayID, int firstIndex, 2770 Value[] values) { 2771 CommandPacket command = new CommandPacket( 2772 JDWPCommands.ArrayReferenceCommandSet.CommandSetID, 2773 JDWPCommands.ArrayReferenceCommandSet.SetValuesCommand); 2774 command.setNextValueAsArrayID(arrayID); 2775 command.setNextValueAsInt(firstIndex); 2776 command.setNextValueAsInt(values.length); 2777 for (int i = 0; i < values.length; i++) { 2778 command.setNextValueAsUntaggedValue(values[i]); 2779 } 2780 2781 checkReply(performCommand(command)); 2782 } 2783 2784 /** 2785 * Sets the value of one or more static fields 2786 * 2787 * @param classID 2788 * The class type ID. 2789 * @param fieldIDs 2790 * An array of fields IDs 2791 * @param values 2792 * An array of Value objects representing each value to set 2793 */ setStaticFieldsValues(long classID, long[] fieldIDs, Value[] values)2794 public final void setStaticFieldsValues(long classID, long[] fieldIDs, 2795 Value[] values) { 2796 if (fieldIDs.length != values.length) { 2797 throw new TestErrorException( 2798 "Number of fields doesn't correspond to number of their values"); 2799 } 2800 2801 CommandPacket command = new CommandPacket( 2802 JDWPCommands.ClassTypeCommandSet.CommandSetID, 2803 JDWPCommands.ClassTypeCommandSet.SetValuesCommand); 2804 command.setNextValueAsClassID(classID); 2805 command.setNextValueAsInt(fieldIDs.length); 2806 for (int i = 0; i < fieldIDs.length; i++) { 2807 command.setNextValueAsFieldID(fieldIDs[i]); 2808 command.setNextValueAsUntaggedValue(values[i]); 2809 } 2810 2811 checkReply(performCommand(command)); 2812 } 2813 2814 /** 2815 * Creates java String in target VM with the given value. 2816 * 2817 * @param value 2818 * The value of the string. 2819 * @return The string id. 2820 */ createString(String value)2821 public final long createString(String value) { 2822 CommandPacket command = new CommandPacket( 2823 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 2824 JDWPCommands.VirtualMachineCommandSet.CreateStringCommand); 2825 command.setNextValueAsString(value); 2826 ReplyPacket reply = checkReply(performCommand(command)); 2827 return reply.getNextValueAsStringID(); 2828 } 2829 2830 /** 2831 * Processes JDWP PopFrames command from StackFrame command set. 2832 * 2833 * @param frame 2834 * The instance of Frame. 2835 */ popFrame(Frame frame)2836 public final void popFrame(Frame frame) { 2837 CommandPacket command = new CommandPacket( 2838 JDWPCommands.StackFrameCommandSet.CommandSetID, 2839 JDWPCommands.StackFrameCommandSet.PopFramesCommand); 2840 command.setNextValueAsThreadID(frame.getThreadID()); 2841 command.setNextValueAsFrameID(frame.getID()); 2842 checkReply(performCommand(command)); 2843 } 2844 2845 /** 2846 * Invokes a member method of the given object. 2847 * 2848 * @param objectID 2849 * The object ID. 2850 * @param threadID 2851 * The thread ID. 2852 * @param methodName 2853 * The name of method for the invocation. 2854 * @param args 2855 * The arguments for the invocation. 2856 * @param options 2857 * The invocation options. 2858 * @return ReplyPacket for corresponding command 2859 */ invokeInstanceMethod(long objectID, long threadID, String methodName, Value[] args, int options)2860 public final ReplyPacket invokeInstanceMethod(long objectID, long threadID, 2861 String methodName, Value[] args, int options) { 2862 long classID = getReferenceType(objectID); 2863 long methodID = getMethodID(classID, methodName); 2864 CommandPacket command = new CommandPacket( 2865 JDWPCommands.ObjectReferenceCommandSet.CommandSetID, 2866 JDWPCommands.ObjectReferenceCommandSet.InvokeMethodCommand); 2867 command.setNextValueAsObjectID(objectID); 2868 command.setNextValueAsThreadID(threadID); 2869 command.setNextValueAsClassID(classID); 2870 command.setNextValueAsMethodID(methodID); 2871 command.setNextValueAsInt(args.length); 2872 for (int i = 0; i < args.length; i++) { 2873 command.setNextValueAsValue(args[i]); 2874 } 2875 command.setNextValueAsInt(options); 2876 2877 return checkReply(performCommand(command)); 2878 } 2879 2880 /** 2881 * Invokes a static method of the given class. 2882 * 2883 * @param classID 2884 * The class type ID. 2885 * @param threadID 2886 * The thread ID. 2887 * @param methodName 2888 * The name of method for the invocation. 2889 * @param args 2890 * The arguments for the invocation. 2891 * @param options 2892 * The invocation options. 2893 * @return ReplyPacket for corresponding command 2894 */ invokeStaticMethod(long classID, long threadID, String methodName, Value[] args, int options)2895 public final ReplyPacket invokeStaticMethod(long classID, long threadID, 2896 String methodName, Value[] args, int options) { 2897 long methodID = getMethodID(classID, methodName); 2898 CommandPacket command = new CommandPacket( 2899 JDWPCommands.ClassTypeCommandSet.CommandSetID, 2900 JDWPCommands.ClassTypeCommandSet.InvokeMethodCommand); 2901 command.setNextValueAsClassID(classID); 2902 command.setNextValueAsThreadID(threadID); 2903 command.setNextValueAsMethodID(methodID); 2904 command.setNextValueAsInt(args.length); 2905 for (int i = 0; i < args.length; i++) { 2906 command.setNextValueAsValue(args[i]); 2907 } 2908 command.setNextValueAsInt(options); 2909 2910 return checkReply(performCommand(command)); 2911 } 2912 } 2913