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