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