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