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