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