• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  */
18 
19 /**
20  * @author Vitaly A. Provodin
21  */
22 
23 package org.apache.harmony.jpda.tests.framework.jdwp;
24 
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.Iterator;
28 import java.util.List;
29 
30 import org.apache.harmony.jpda.tests.framework.Breakpoint;
31 import org.apache.harmony.jpda.tests.framework.LogWriter;
32 import org.apache.harmony.jpda.tests.framework.TestErrorException;
33 import org.apache.harmony.jpda.tests.framework.TestOptions;
34 import org.apache.harmony.jpda.tests.framework.jdwp.Capabilities;
35 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
36 import org.apache.harmony.jpda.tests.framework.jdwp.Event;
37 import org.apache.harmony.jpda.tests.framework.jdwp.EventMod;
38 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
39 import org.apache.harmony.jpda.tests.framework.jdwp.Location;
40 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
41 import org.apache.harmony.jpda.tests.framework.jdwp.TransportWrapper;
42 import org.apache.harmony.jpda.tests.framework.jdwp.TypesLengths;
43 import org.apache.harmony.jpda.tests.framework.jdwp.Frame.Variable;
44 import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.ReplyErrorCodeException;
45 import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.TimeoutException;
46 
47 /**
48  * This class provides convenient way for communicating with debuggee VM using
49  * JDWP packets.
50  * <p>
51  * Most methods can throw ReplyErrorCodeException if error occurred in execution
52  * of corresponding JDWP command or TestErrorException if any other error
53  * occurred.
54  */
55 public class VmMirror {
56 
57     /** Target VM Capabilities. */
58     private Capabilities targetVMCapabilities;
59 
60     /** Transport used to sent and receive packets. */
61     private TransportWrapper connection;
62 
63     /** PacketDispatcher thread used for asynchronous reading packets. */
64     private PacketDispatcher packetDispatcher;
65 
66     /** Test run options. */
67     protected TestOptions config;
68 
69     /** Log to write messages. */
70     protected LogWriter logWriter;
71 
72     /**
73      * Creates new VmMirror instance for given test run options.
74      *
75      * @param config
76      *            test run options
77      * @param logWriter
78      *            log writer
79      */
VmMirror(TestOptions config, LogWriter logWriter)80     public VmMirror(TestOptions config, LogWriter logWriter) {
81         connection = null;
82         this.config = config;
83         this.logWriter = logWriter;
84     }
85 
86     /**
87      * Checks error code of given reply packet and throws
88      * ReplyErrorCodeException if any error detected.
89      *
90      * @param reply
91      *            reply packet to check
92      * @return ReplyPacket unchanged reply packet
93      */
checkReply(ReplyPacket reply)94     public ReplyPacket checkReply(ReplyPacket reply) {
95         if (reply.getErrorCode() != JDWPConstants.Error.NONE)
96             throw new ReplyErrorCodeException(reply.getErrorCode());
97         return reply;
98     }
99 
100     /**
101      * Sets breakpoint to given location with suspend policy ALL.
102      *
103      * @param location
104      *            Location of breakpoint
105      * @return ReplyPacket for corresponding command
106      */
setBreakpoint(Location location)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      */
setBreakpoint(Location location, byte suspendPolicy)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      */
setCountableBreakpoint(byte typeTag, Breakpoint breakpoint, byte suspendPolicy, int count)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      */
setBreakpointAtMethodBegin(long classID, String methodName)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      */
setBreakpointAtMethodBegin(long classID, String methodName, byte suspendPolicy)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      */
waitForBreakpoint(int requestID)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      */
clearBreakpoint(int requestID)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      */
ClearAllBreakpoints()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      */
capabilities()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      */
canRedefineClasses()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      */
canPopFrames()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      */
canGetSourceDebugExtension()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      */
canRequestVMDeathEvent()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      */
canSetDefaultStratum()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      */
canUseSourceNameFilters()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      */
canGetConstantPool()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      */
canForceEarlyReturn()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      */
resume()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      */
resumeThread(long threadID)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      */
suspend()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      */
suspendThread(long threadID)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      */
dispose()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      */
exit(int exitCode)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      */
adjustTypeLength()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      */
getTypeID(String typeSignature, byte classTypeTag)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      */
getClassID(String classSignature)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      */
getThreadID(String threadName)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      */
getAllThreadID()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      */
getClassSignature(long classID)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      */
getThreadName(long threadID)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      */
getThreadStatus(long threadID)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      */
getThreadSuspendCount(long threadID)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      */
getThreadGroupName(long groupID)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      */
getInterfaceID(String interfaceSignature)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      */
getArrayID(String arraySignature)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      */
getRequestID(ReplyPacket request)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      */
getFieldID(long classID, String fieldName)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      */
getFieldID(ReplyPacket request, String field)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      */
getMethodID(long classID, String methodName)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      */
getMethodName(long classID, long methodID)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      */
setClassPrepared(String classRegexp)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      */
setClassPrepared(long referenceTypeID)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      */
setClassPreparedForSourceNameMatch(String sourceNamePattern)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      */
setClassUnload(String classRegexp)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      */
setClassUnload(long referenceTypeID)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      */
setClassLoad(String classSignature)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      */
setClassLoad(long referenceTypeID)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      */
setMonitorContendedEnterForClassOnly(long referenceTypeID)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      */
setMonitorContendedEnterForClassMatch(String classRegexp)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      */
setMonitorContendedEnteredForClassOnly(long referenceTypeID)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      */
setMonitorContendedEnteredForClassMatch(String classRegexp)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      */
setMonitorWaitForClassOnly(long referenceTypeID)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      */
setMonitorWaitForClassMatch(String classRegexp)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      */
setMonitorWaitForClassExclude(String classRegexp)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      */
setMonitorWaitedForClassOnly(long referenceTypeID)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      */
setMonitorWaitedForClassMatch(String classRegexp)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      */
setMonitorWaitedForClassExclude(String classRegexp)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      */
setEvent(Event event)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      */
getMethods(long classReferenceTypeID)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      */
getClassBySignature(String classSignature)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      */
getFieldsInClass(long referenceTypeID)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      */
setException(String exceptionSignature, boolean caught, boolean uncaught)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      */
setException(long exceptionID, boolean caught, boolean uncaught)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      */
setMethodEntry(String classRegexp)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      */
setMethodExit(String classRegexp)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      */
setMethodExitWithReturnValue(String classRegexp)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      */
setFieldAccess(String classSignature, byte classTypeTag, String fieldName)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      */
setFieldModification(String classSignature, byte classTypeTag, String fieldName)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      */
setStep(long threadID, int stepSize, int stepDepth)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      */
setStep(String[] classRegexp, long threadID, int stepSize, int stepDepth)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      */
setThreadStart(byte suspendPolicy)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      */
setThreadEnd(byte suspendPolicy)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 
setClassOnlyEvent(byte eventKind, byte suspendPolicy, long classId)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 
setClassMatchEvent(byte eventKind, byte suspendPolicy, String pattern)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 
setClassExcludeEvent(byte eventKind, byte suspendPolicy, String pattern)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      */
clearEvent(byte eventKind, int requestID)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      */
performCommand(CommandPacket command)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      */
performCommand(CommandPacket command, long timeout)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      */
sendCommand(CommandPacket command)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      */
receiveReply(int commandId)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      */
receiveReply(int commandId, long timeout)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      */
receiveEvent()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      */
receiveEvent(long timeout)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      */
receiveCertainEvent(byte eventKind)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      */
getConnection()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      */
setConnection(TransportWrapper connection)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      */
closeConnection()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      */
getFrameCount(long threadID)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      */
getAllThreadFrames(long threadID)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      */
getThreadFrames(long threadID, int startIndex, int length)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      */
getVariableTable(long classID, long methodID)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      */
getFrameValues(Frame frame)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      */
getSuperclassId(long classID)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      */
getReferenceType(long objectID)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      */
getClassObjectId(long refType)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      */
getLineTable(long refType, long methodID)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      */
getObjectReferenceValues(long objectID, long[] fieldIDs)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      */
getReferenceTypeValues(long refTypeID, long[] fieldIDs)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      */
getReferenceTypeValue(long refTypeID, long fieldID)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      */
getThisObject(long threadID, long frameID)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      */
getAllFields(long classID)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      */
getReflectedType(long classObjectID)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      */
getReferenceTypeSignature(long refTypeID)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      */
getThreadGroupID(long threadID)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      */
isThreadSuspended(long threadID)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      */
getMethodSignature(long classID, long methodID)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      */
getStringValue(long objectID)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      */
getArrayValues(long objectID)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      */
getLineNumber(long classID, long methodID, long codeIndex)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      */
getLineCodeIndex(long classID, long methodID, int lineNumber)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      */
getLocalVars(Frame frame)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      */
setLocalVars(Frame frame, Variable[] vars, Value[] values)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      */
setInstanceFieldsValues(long objectID, long[] fieldIDs, Value[] values)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      */
setArrayValues(long arrayID, int firstIndex, Value[] values)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      */
setStaticFieldsValues(long classID, long[] fieldIDs, Value[] values)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      */
createString(String value)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      */
popFrame(Frame frame)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      */
invokeInstanceMethod(long objectID, long threadID, String methodName, Value[] args, int options)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      */
invokeStaticMethod(long classID, long threadID, String methodName, Value[] args, int options)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