You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ge...@apache.org on 2006/11/28 18:49:31 UTC

svn commit: r480141 [20/38] - in /harmony/enhanced/jdktools/trunk/modules/jpda: ./ doc/ doc/images/ make/ src/ src/common/ src/common/other/ src/common/other/jpda/ src/common/other/jpda/jdwp/ src/common/other/jpda/jdwp/agent/ src/common/other/jpda/jdwp...

Added: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/VmMirror.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/VmMirror.java?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/VmMirror.java (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/VmMirror.java Tue Nov 28 09:49:08 2006
@@ -0,0 +1,2600 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Vitaly A. Provodin
+ * @version $Revision: 1.7 $
+ */
+
+package org.apache.harmony.jpda.tests.framework.jdwp;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.harmony.jpda.tests.framework.Breakpoint;
+import org.apache.harmony.jpda.tests.framework.LogWriter;
+import org.apache.harmony.jpda.tests.framework.TestErrorException;
+import org.apache.harmony.jpda.tests.framework.TestOptions;
+import org.apache.harmony.jpda.tests.framework.jdwp.Capabilities;
+import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
+import org.apache.harmony.jpda.tests.framework.jdwp.Event;
+import org.apache.harmony.jpda.tests.framework.jdwp.EventMod;
+import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
+import org.apache.harmony.jpda.tests.framework.jdwp.Location;
+import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
+import org.apache.harmony.jpda.tests.framework.jdwp.TransportWrapper;
+import org.apache.harmony.jpda.tests.framework.jdwp.TypesLengths;
+import org.apache.harmony.jpda.tests.framework.jdwp.Frame.Variable;
+import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.ReplyErrorCodeException;
+import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.TimeoutException;
+
+/**
+ * This class provides convenient way for communicating with debuggee VM using
+ * JDWP packets.
+ * <p>
+ * Most methods can throw ReplyErrorCodeException if error occurred in execution
+ * of corresponding JDWP command or TestErrorException if any other error
+ * occurred.
+ */
+public class VmMirror {
+
+    /** Target VM Capabilities. */
+    public Capabilities targetVMCapabilities;
+
+    /** Transport used to sent and receive packets. */
+    private TransportWrapper connection;
+
+    /** PacketDispatcher thread used for asynchronous reading packets. */
+    private PacketDispatcher packetDispatcher;
+
+    /** Test run options. */
+    protected TestOptions config;
+
+    /** Log to write messages. */
+    protected LogWriter logWriter;
+
+    /**
+     * Creates new VmMirror instance for given test run options.
+     * 
+     * @param config test run options
+     * @param logWriter log writer
+     */
+    public VmMirror(TestOptions config, LogWriter logWriter) {
+        connection = null;
+        this.config = config;
+        this.logWriter = logWriter;
+    }
+
+    /**
+     * Checks error code of given reply packet and throws
+     * ReplyErrorCodeException if any error detected.
+     * 
+     * @param reply
+     *            reply packet to check
+     * @return ReplyPacket unchanged reply packet
+     */
+    public ReplyPacket checkReply(ReplyPacket reply) {
+        if (reply.getErrorCode() != JDWPConstants.Error.NONE)
+            throw new ReplyErrorCodeException(reply.getErrorCode());
+        return reply;
+    }
+
+    /**
+     * Sets breakpoint to given location.
+     * 
+     * @param typeTag
+     * @param breakpoint
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setBreakpoint(byte typeTag, Breakpoint breakpoint) {
+
+        return setBreakpoint(typeTag, breakpoint,
+                JDWPConstants.SuspendPolicy.ALL);
+    }
+
+    /**
+     * Sets breakpoint to given location.
+     * 
+     * @param typeTag
+     * @param breakpoint
+     * @param suspendPolicy
+     *            Suspend policy for a breakpoint being created
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setBreakpoint(byte typeTag, Breakpoint breakpoint,
+            byte suspendPolicy) {
+        // Get Class reference ID
+        long typeID = getTypeID(breakpoint.className, typeTag);
+
+        // Get Method reference ID
+        long methodID = getMethodID(typeID, breakpoint.methodName);
+
+        // Fill location
+        Location location = new Location(typeTag, typeID, methodID,
+                breakpoint.index);
+
+        // Set breakpoint
+        return setBreakpoint(location, suspendPolicy);
+    }
+
+    /**
+     * Sets breakpoint to given location.
+     * 
+     * @param location
+     *            Location of breakpoint
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setBreakpoint(Location location) {
+
+        return setBreakpoint(location, JDWPConstants.SuspendPolicy.ALL);
+    }
+
+    /**
+     * Sets breakpoint to given location
+     * 
+     * @param location
+     *            Location of breakpoint
+     * @param suspendPolicy
+     *            Suspend policy for a breakpoint being created
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setBreakpoint(Location location, byte suspendPolicy) {
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.BREAKPOINT;
+
+        // EventMod[] mods = new EventMod[1];
+        EventMod[] mods = new EventMod[] { new EventMod() };
+
+        mods[0].loc = location;
+        mods[0].modKind = EventMod.ModKind.LocationOnly;
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        // Set breakpoint
+        return setEvent(event);
+    }
+
+    /**
+     * Sets breakpoint that triggers only on a certain occurrence to a given
+     * location
+     * 
+     * @param typeTag
+     * @param breakpoint
+     * @param suspendPolicy
+     *            Suspend policy for a breakpoint being created
+     * @param count
+     *            Limit the requested event to be reported at most once after a
+     *            given number of occurrences
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setCountableBreakpoint(byte typeTag,
+            Breakpoint breakpoint, byte suspendPolicy, int count) {
+        long typeID = getTypeID(breakpoint.className, typeTag);
+
+        // Get Method reference ID
+        long methodID = getMethodID(typeID, breakpoint.methodName);
+
+        byte eventKind = JDWPConstants.EventKind.BREAKPOINT;
+
+        EventMod mod1 = new EventMod();
+        mod1.modKind = EventMod.ModKind.LocationOnly;
+        mod1.loc = new Location(typeTag, typeID, methodID, breakpoint.index);
+
+        EventMod mod2 = new EventMod();
+        mod2.modKind = EventMod.ModKind.Count;
+        mod2.count = count;
+
+        EventMod[] mods = new EventMod[] { mod1, mod2 };
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        // Set breakpoint
+        return setEvent(event);
+    }
+
+    /**
+     * Sets breakpoint at the beginning of method with name <i>methodName</i>.
+     * 
+     * @param classID
+     *            id of class with required method
+     * @param methodName
+     *            name of required method
+     * @return requestID id of request
+     */
+    public long setBreakpointAtMethodBegin(long classID, String methodName) {
+        long requestID;
+
+        long methodID = getMethodID(classID, methodName);
+
+        ReplyPacket lineTableReply = getLineTable(classID, methodID);
+        if (lineTableReply.getErrorCode() != JDWPConstants.Error.NONE) {
+            throw new TestErrorException(
+                    "Command getLineTable returned error code: "
+                            + lineTableReply.getErrorCode()
+                            + " - "
+                            + JDWPConstants.Error.getName(lineTableReply
+                                    .getErrorCode()));
+        }
+
+        lineTableReply.getNextValueAsLong();
+        // Lowest valid code index for the method
+
+        lineTableReply.getNextValueAsLong();
+        // Highest valid code index for the method
+
+        // int numberOfLines =
+        lineTableReply.getNextValueAsInt();
+
+        long lineCodeIndex = lineTableReply.getNextValueAsLong();
+
+        // set breakpoint inside checked method
+        Location breakpointLocation = new Location(JDWPConstants.TypeTag.CLASS,
+                classID, methodID, lineCodeIndex);
+
+        ReplyPacket reply = setBreakpoint(breakpointLocation);
+        checkReply(reply);
+
+        requestID = reply.getNextValueAsInt();
+
+        return requestID;
+    }
+
+    /**
+     * Waits for stop on breakpoint and gets id of thread where it stopped.
+     * 
+     * @param requestID
+     *            id of request for breakpoint
+     * @return threadID id of thread, where we stop on breakpoint
+     */
+    public long waitForBreakpoint(long requestID) {
+        // receive event
+        CommandPacket event = null;
+        event = receiveEvent();
+
+        event.getNextValueAsByte();
+        // suspendPolicy - is not used here
+
+        // int numberOfEvents =
+        event.getNextValueAsInt();
+
+        long breakpointThreadID = 0;
+        ParsedEvent[] eventParsed = ParsedEvent.parseEventPacket(event);
+
+        if (eventParsed.length != 1) {
+            throw new TestErrorException("Received " + eventParsed.length
+                    + " events instead of 1 BREAKPOINT_EVENT");
+        }
+
+        // check if received event is for breakpoint
+        if (eventParsed[0].getEventKind() == JDWPConstants.EventKind.BREAKPOINT) {
+            breakpointThreadID = ((ParsedEvent.Event_BREAKPOINT) eventParsed[0])
+                    .getThreadID();
+
+        } else {
+            throw new TestErrorException(
+                    "Kind of received event is not BREAKPOINT_EVENT: "
+                            + eventParsed[0].getEventKind());
+
+        }
+
+        if (eventParsed[0].getRequestID() != requestID) {
+            throw new TestErrorException(
+                    "Received BREAKPOINT_EVENT with another requestID: "
+                            + eventParsed[0].getRequestID());
+        }
+
+        return breakpointThreadID;
+    }
+
+    /**
+     * Removes breakpoint according to specified requestID.
+     * 
+     * @param requestID
+     *            for given breakpoint
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket clearBreakpoint(int requestID) {
+
+        // Create new command packet
+        CommandPacket commandPacket = new CommandPacket();
+
+        // Set command. "2" - is ID of Clear command in EventRequest Command Set
+        commandPacket
+                .setCommand(JDWPCommands.EventRequestCommandSet.ClearCommand);
+
+        // Set command set. "15" - is ID of EventRequest Command Set
+        commandPacket
+                .setCommandSet(JDWPCommands.EventRequestCommandSet.CommandSetID);
+
+        // Set outgoing data
+        // Set eventKind
+        commandPacket.setNextValueAsByte(JDWPConstants.EventKind.BREAKPOINT);
+
+        // Set suspendPolicy
+        commandPacket.setNextValueAsInt(requestID);
+
+        // Send packet
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Removes all breakpoints.
+     * 
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket ClearAllBreakpoints() {
+
+        // Create new command packet
+        CommandPacket commandPacket = new CommandPacket();
+
+        // Set command. "3" - is ID of ClearAllBreakpoints command in
+        // EventRequest Command Set
+        commandPacket
+                .setCommand(JDWPCommands.EventRequestCommandSet.ClearAllBreakpointsCommand);
+
+        // Set command set. "15" - is ID of EventRequest Command Set
+        commandPacket
+                .setCommandSet(JDWPCommands.EventRequestCommandSet.CommandSetID);
+
+        // Send packet
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Requests debuggee VM capabilities. Function parses reply packet of
+     * VirtualMachine::CapabilitiesNew command, creates and fills class Capabilities with
+     * returned info.
+     * 
+     * @return ReplyPacket useless, already parsed reply packet.
+     */
+    public ReplyPacket capabilities() {
+
+        // Create new command packet
+        CommandPacket commandPacket = new CommandPacket();
+
+        // Set command. "17" - is ID of CapabilitiesNew command in
+        // VirtualMachine Command Set
+        commandPacket
+                .setCommand(JDWPCommands.VirtualMachineCommandSet.CapabilitiesNewCommand);
+
+        // Set command set. "1" - is ID of VirtualMachine Command Set
+        commandPacket
+                .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID);
+
+        // Send packet
+        ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
+        
+        targetVMCapabilities = new Capabilities();
+
+        // Set capabilities
+        targetVMCapabilities.canWatchFieldModification = replyPacket
+                .getNextValueAsBoolean();
+        targetVMCapabilities.canWatchFieldAccess = replyPacket
+                .getNextValueAsBoolean();
+        targetVMCapabilities.canGetBytecodes = replyPacket
+                .getNextValueAsBoolean();
+        targetVMCapabilities.canGetSyntheticAttribute = replyPacket
+                .getNextValueAsBoolean();
+        targetVMCapabilities.canGetOwnedMonitorInfo = replyPacket
+                .getNextValueAsBoolean();
+        targetVMCapabilities.canGetCurrentContendedMonitor = replyPacket
+                .getNextValueAsBoolean();
+        targetVMCapabilities.canGetMonitorInfo = replyPacket
+                .getNextValueAsBoolean();
+        targetVMCapabilities.canRedefineClasses = replyPacket
+                .getNextValueAsBoolean();
+        targetVMCapabilities.canAddMethod = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.canUnrestrictedlyRedefineClasses = replyPacket
+                .getNextValueAsBoolean();
+        targetVMCapabilities.canPopFrames = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.canUseInstanceFilters = replyPacket
+                .getNextValueAsBoolean();
+        targetVMCapabilities.canGetSourceDebugExtension = replyPacket
+                .getNextValueAsBoolean();
+        targetVMCapabilities.canRequestVMDeathEvent = replyPacket
+                .getNextValueAsBoolean();
+        targetVMCapabilities.canSetDefaultStratum = replyPacket
+                .getNextValueAsBoolean();
+        targetVMCapabilities.reserved16 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved17 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved18 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved19 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved20 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved21 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved22 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved23 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved24 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved25 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved26 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved27 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved28 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved29 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved30 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved31 = replyPacket.getNextValueAsBoolean();
+        targetVMCapabilities.reserved32 = replyPacket.getNextValueAsBoolean();
+
+        return replyPacket;
+    }
+
+    /**
+     * Resumes debuggee VM.
+     * 
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket resume() {
+        CommandPacket commandPacket = new CommandPacket(
+                JDWPCommands.VirtualMachineCommandSet.CommandSetID,
+                JDWPCommands.VirtualMachineCommandSet.ResumeCommand);
+
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Resumes specified thread on target Virtual Machine
+     * 
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket resumeThread(long threadID) {
+        CommandPacket commandPacket = new CommandPacket(
+                JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
+                JDWPCommands.ThreadReferenceCommandSet.ResumeCommand);
+
+        commandPacket.setNextValueAsThreadID(threadID);
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Suspends debuggee VM.
+     * 
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket suspend() {
+        CommandPacket commandPacket = new CommandPacket(
+                JDWPCommands.VirtualMachineCommandSet.CommandSetID,
+                JDWPCommands.VirtualMachineCommandSet.SuspendCommand);
+
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Suspends specified thread in debuggee VM.
+     * 
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket suspendThread(long threadID) {
+        CommandPacket commandPacket = new CommandPacket(
+                JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
+                JDWPCommands.ThreadReferenceCommandSet.SuspendCommand);
+
+        commandPacket.setNextValueAsThreadID(threadID);
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Disposes connection to debuggee VM.
+     * 
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket dispose() {
+        // Create new command packet
+        CommandPacket commandPacket = new CommandPacket();
+        commandPacket
+                .setCommand(JDWPCommands.VirtualMachineCommandSet.DisposeCommand);
+        commandPacket
+                .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID);
+
+        // Send packet
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Exits debuggee VM process.
+     * 
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket exit(int exitCode) {
+        // Create new command packet
+        CommandPacket commandPacket = new CommandPacket();
+        commandPacket
+                .setCommand(JDWPCommands.VirtualMachineCommandSet.ExitCommand);
+        commandPacket
+                .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID);
+        commandPacket.setNextValueAsInt(exitCode);
+
+        // Send packet
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Adjusts lengths for all VM-specific types.
+     * 
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket adjustTypeLength() {
+        // Create new command packet
+        CommandPacket commandPacket = new CommandPacket();
+        commandPacket
+                .setCommand(JDWPCommands.VirtualMachineCommandSet.IDSizesCommand);
+        commandPacket
+                .setCommandSet(JDWPCommands.VirtualMachineCommandSet.CommandSetID);
+
+        // Send packet
+        ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
+
+        // Get FieldIDSize from ReplyPacket
+        TypesLengths.setTypeLength(TypesLengths.FIELD_ID, replyPacket
+                .getNextValueAsInt());
+
+        // Get MethodIDSize from ReplyPacket
+        TypesLengths.setTypeLength(TypesLengths.METHOD_ID, replyPacket
+                .getNextValueAsInt());
+
+        // Get ObjectIDSize from ReplyPacket
+        TypesLengths.setTypeLength(TypesLengths.OBJECT_ID, replyPacket
+                .getNextValueAsInt());
+
+        // Get ReferenceTypeIDSize from ReplyPacket
+        TypesLengths.setTypeLength(TypesLengths.REFERENCE_TYPE_ID, replyPacket
+                .getNextValueAsInt());
+
+        // Get FrameIDSize from ReplyPacket
+        TypesLengths.setTypeLength(TypesLengths.FRAME_ID, replyPacket
+                .getNextValueAsInt());
+
+        // Adjust all other types lengths
+        TypesLengths.setTypeLength(TypesLengths.ARRAY_ID, TypesLengths
+                .getTypeLength(TypesLengths.OBJECT_ID));
+        TypesLengths.setTypeLength(TypesLengths.STRING_ID, TypesLengths
+                .getTypeLength(TypesLengths.OBJECT_ID));
+        TypesLengths.setTypeLength(TypesLengths.THREAD_ID, TypesLengths
+                .getTypeLength(TypesLengths.OBJECT_ID));
+        TypesLengths.setTypeLength(TypesLengths.THREADGROUP_ID, TypesLengths
+                .getTypeLength(TypesLengths.OBJECT_ID));
+        TypesLengths.setTypeLength(TypesLengths.LOCATION_ID, TypesLengths
+                .getTypeLength(TypesLengths.OBJECT_ID));
+        TypesLengths.setTypeLength(TypesLengths.CLASS_ID, TypesLengths
+                .getTypeLength(TypesLengths.OBJECT_ID));
+        TypesLengths.setTypeLength(TypesLengths.CLASSLOADER_ID, TypesLengths
+                .getTypeLength(TypesLengths.OBJECT_ID));
+        TypesLengths.setTypeLength(TypesLengths.CLASSOBJECT_ID, TypesLengths
+                .getTypeLength(TypesLengths.OBJECT_ID));
+        return replyPacket;
+    }
+
+    /**
+     * Gets TypeID for specified type signature and type tag.
+     * 
+     * @param typeSignature
+     *            type signature
+     * @param classTypeTag
+     *            type tag
+     * @return received TypeID
+     */
+    public long getTypeID(String typeSignature, byte classTypeTag) {
+        int classes = 0;
+        byte refTypeTag = 0;
+        long typeID = -1;
+
+        // Request referenceTypeID for exception
+        ReplyPacket classReference = getClassBySignature(typeSignature);
+
+        // Get referenceTypeID from received packet
+        classes = classReference.getNextValueAsInt();
+        for (int i = 0; i < classes; i++) {
+            refTypeTag = classReference.getNextValueAsByte();
+            if (refTypeTag == classTypeTag) {
+                typeID = classReference.getNextValueAsReferenceTypeID();
+                classReference.getNextValueAsInt();
+                break;
+            } else {
+                classReference.getNextValueAsReferenceTypeID();
+                classReference.getNextValueAsInt();
+                refTypeTag = 0;
+            }
+        }
+        return typeID;
+    }
+
+    /**
+     * Gets ClassID for specified class signature.
+     * 
+     * @param classSignature
+     *            class signature
+     * @return received ClassID
+     */
+    public long getClassID(String classSignature) {
+        return getTypeID(classSignature, JDWPConstants.TypeTag.CLASS);
+    }
+
+    /**
+     * Gets ThreadID for specified thread name.
+     * 
+     * @param threadName
+     *            thread name
+     * @return received ThreadID
+     */
+    public long getThreadID(String threadName) {
+        ReplyPacket request = null;
+        long threadID = -1;
+        long thread = -1;
+        String name = null;
+        int threads = -1;
+
+        // Get All Threads IDs
+        request = getAllThreadID();
+
+        // Get thread ID for threadName
+        threads = request.getNextValueAsInt();
+        for (int i = 0; i < threads; i++) {
+            thread = request.getNextValueAsThreadID();
+            name = getThreadName(thread);
+            if (threadName.equals(name)) {
+                threadID = thread;
+                break;
+            }
+        }
+
+        return threadID;
+    }
+
+    /**
+     * Returns all running thread IDs.
+     * 
+     * @return received reply packet
+     */
+    public ReplyPacket getAllThreadID() {
+        // Create new command packet
+        CommandPacket commandPacket = new CommandPacket(
+                JDWPCommands.VirtualMachineCommandSet.CommandSetID,
+                JDWPCommands.VirtualMachineCommandSet.AllThreadsCommand);
+
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Gets class signature for specified class ID.
+     * 
+     * @param classID
+     *            class ID
+     * @return received class signature
+     */
+    public String getClassSignature(long classID) {
+        // Create new command packet
+        CommandPacket commandPacket = new CommandPacket(
+                JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
+                JDWPCommands.ReferenceTypeCommandSet.SignatureCommand);
+        commandPacket.setNextValueAsReferenceTypeID(classID);
+        ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
+        return replyPacket.getNextValueAsString();
+    }
+
+    /**
+     * Returns thread name for specified <code>threadID</code>.
+     * 
+     * @param threadID
+     *            thread ID
+     * @return thread name
+     */
+    public String getThreadName(long threadID) {
+        // Create new command packet
+        CommandPacket commandPacket = new CommandPacket(
+                JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
+                JDWPCommands.ThreadReferenceCommandSet.NameCommand);
+        commandPacket.setNextValueAsThreadID(threadID);
+        ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
+        return replyPacket.getNextValueAsString();
+    }
+
+    /**
+     * Returns thread status for specified <code>threadID</code>.
+     * 
+     * @param threadID
+     *            thread ID
+     * @return thread status
+     */
+    public int getThreadStatus(long threadID) {
+        CommandPacket commandPacket = new CommandPacket(
+                JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
+                JDWPCommands.ThreadReferenceCommandSet.StatusCommand);
+        commandPacket.setNextValueAsThreadID(threadID);
+        ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
+        return replyPacket.getNextValueAsInt();
+    }
+
+    /**
+     * Returns name of thread group for specified <code>groupID</code>
+     * 
+     * @param groupID
+     *            thread group ID
+     * 
+     * @return name of thread group
+     */
+    public String getThreadGroupName(long groupID) {
+        // Create new command packet
+        CommandPacket commandPacket = new CommandPacket(
+                JDWPCommands.ThreadGroupReferenceCommandSet.CommandSetID,
+                JDWPCommands.ThreadGroupReferenceCommandSet.NameCommand);
+        commandPacket.setNextValueAsReferenceTypeID(groupID);
+        ReplyPacket replyPacket = checkReply(performCommand(commandPacket));
+        return replyPacket.getNextValueAsString();
+    }
+
+    /**
+     * Gets InterfaceID for specified interface signature.
+     * 
+     * @param interfaceSignature
+     *            interface signature
+     * @return received ClassID
+     */
+    public long getInterfaceID(String interfaceSignature) {
+        return getTypeID(interfaceSignature, JDWPConstants.TypeTag.INTERFACE);
+    }
+
+    /**
+     * Gets ArrayID for specified array signature.
+     * 
+     * @param arraySignature
+     *            array signature
+     * @return received ArrayID
+     */
+    public long getArrayID(String arraySignature) {
+        return getTypeID(arraySignature, JDWPConstants.TypeTag.INTERFACE);
+    }
+
+    /**
+     * Gets RequestID from specified ReplyPacket.
+     * 
+     * @param request
+     *            ReplyPacket with RequestID
+     * @return received RequestID
+     */
+    public int getRequestID(ReplyPacket request) {
+        return request.getNextValueAsInt();
+    }
+
+    /**
+     * Returns FieldID for specified class and field name.
+     * 
+     * @param classID
+     *            ClassID to find field
+     * @param fieldName
+     *            field name
+     * @return received FieldID
+     */
+    public long getFieldID(long classID, String fieldName) {
+        ReplyPacket reply = getFieldsInClass(classID);
+        return getFieldID(reply, fieldName);
+    }
+
+    /**
+     * Gets FieldID from ReplyPacket.
+     * 
+     * @param request
+     *            ReplyPacket for request
+     * @param field
+     *            field name to get ID for
+     * @return received FieldID
+     */
+    public long getFieldID(ReplyPacket request, String field) {
+        long fieldID = -1;
+        String fieldName;
+        // Get fieldID from received packet
+        int count = request.getNextValueAsInt();
+        for (int i = 0; i < count; i++) {
+            fieldID = request.getNextValueAsFieldID();
+            fieldName = request.getNextValueAsString();
+            if (field.equals(fieldName)) {
+                request.getNextValueAsString();
+                request.getNextValueAsInt();
+                break;
+            } else {
+                request.getNextValueAsString();
+                request.getNextValueAsInt();
+                fieldID = 0;
+                fieldName = null;
+            }
+        }
+        return fieldID;
+    }
+
+    /**
+     * Gets Method ID for specified class and method name.
+     * 
+     * @param classID
+     *            class to find method
+     * @param methodName
+     *            method name
+     * @return received MethodID
+     */
+    public long getMethodID(long classID, String methodName) {
+        ReplyPacket reply;
+        int declared = 0;
+        String method = null;
+        long methodID = -1;
+
+        // Get Method reference ID
+        reply = getMethods(classID);
+
+        // Get methodID from received packet
+        declared = reply.getNextValueAsInt();
+        for (int i = 0; i < declared; i++) {
+            methodID = reply.getNextValueAsMethodID();
+            method = reply.getNextValueAsString();
+            if (methodName.equals(method)) {
+                // If this method name is the same as requested
+                reply.getNextValueAsString();
+                reply.getNextValueAsInt();
+                break;
+            } else {
+                // If this method name is not the requested one
+                reply.getNextValueAsString();
+                reply.getNextValueAsInt();
+                methodID = -1;
+                method = null;
+            }
+        }
+        return methodID;
+    }
+
+    /**
+     * Returns method name for specified pair of classID and methodID.
+     * 
+     * @param classID
+     * @param methodID
+     * @return method name
+     */
+    public String getMethodName(long classID, long methodID) {
+        CommandPacket packet = new CommandPacket(
+                JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
+                JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
+        packet.setNextValueAsReferenceTypeID(classID);
+        ReplyPacket reply = performCommand(packet);
+
+        int declared = reply.getNextValueAsInt();
+        long mID;
+        String value = null;
+        String methodName = "";
+        for (int i = 0; i < declared; i++) {
+            mID = reply.getNextValueAsMethodID();
+            methodName = reply.getNextValueAsString();
+            reply.getNextValueAsString();
+            reply.getNextValueAsInt();
+            if (mID == methodID) {
+                value = methodName;
+                break;
+            }
+        }
+        return value;
+    }
+
+    /**
+     * Sets ClassPrepare event request for given class name pattern.
+     * 
+     * @param classRegexp
+     *            Required class pattern. Matches are limited to exact matches
+     *            of the given class pattern and matches of patterns that begin
+     *            or end with '*'; for example, "*.Foo" or "java.*".
+     * @return ReplyPacket for setting request.
+     */
+    public ReplyPacket setClassPrepared(String classRegexp) {
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.CLASS_PREPARE;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        // EventMod[] mods = new EventMod[1];
+        EventMod[] mods = new EventMod[] { new EventMod() };
+        mods[0].classPattern = classRegexp;
+        mods[0].modKind = EventMod.ModKind.ClassMatch;
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        // Set event
+        return setEvent(event);
+    }
+
+    /**
+     * Set ClassPrepare event request for given class ID.
+     * 
+     * @param referenceTypeID
+     *            class referenceTypeID
+     * @return ReplyPacket for setting request
+     */
+    public ReplyPacket setClassPrepared(long referenceTypeID) {
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.CLASS_PREPARE;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        // EventMod[] mods = new EventMod[1];
+        EventMod[] mods = new EventMod[] { new EventMod() };
+        mods[0].clazz = referenceTypeID;
+        mods[0].modKind = EventMod.ModKind.ClassOnly;
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        // Set event
+        return setEvent(event);
+    }
+
+    /**
+     * Sets ClassUnload event request for given class signature.
+     * 
+     * @param classSignature
+     *            class signature
+     * @return ReplyPacket for setting request
+     */
+    public ReplyPacket setClassUnload(String classSignature) {
+        long typeID;
+
+        // Request referenceTypeID for class
+        typeID = getClassID(classSignature);
+
+        // Set corresponding event
+        return setClassUnload(typeID);
+    }
+
+    /**
+     * Set ClassUnload event request for given class ID.
+     * 
+     * @param referenceTypeID
+     *            class referenceTypeID
+     * @return ReplyPacket for setting request
+     */
+    public ReplyPacket setClassUnload(long referenceTypeID) {
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.CLASS_UNLOAD;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        // EventMod[] mods = new EventMod[1];
+        EventMod[] mods = new EventMod[] { new EventMod() };
+        mods[0].clazz = referenceTypeID;
+        mods[0].modKind = EventMod.ModKind.ClassOnly;
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        // Set event
+        return setEvent(event);
+    }
+
+    /**
+     * Sets ClassLoad event request for given class signature.
+     * 
+     * @param classSignature
+     *            class signature
+     * @return ReplyPacket for setting request
+     */
+    public ReplyPacket setClassLoad(String classSignature) {
+        long typeID;
+
+        // Request referenceTypeID for class
+        typeID = getClassID(classSignature);
+
+        // Set corresponding event
+        return setClassLoad(typeID);
+    }
+
+    /**
+     * Set ClassLoad event request for given class ID.
+     * 
+     * @param referenceTypeID
+     *            class referenceTypeID
+     * @return ReplyPacket for setting request
+     */
+    public ReplyPacket setClassLoad(long referenceTypeID) {
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.CLASS_LOAD;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        EventMod[] mods = new EventMod[] { new EventMod() };
+        mods[0].clazz = referenceTypeID;
+        mods[0].modKind = EventMod.ModKind.ClassOnly;
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        // Set event
+        return setEvent(event);
+    }
+
+    /**
+     * Set event request for given event.
+     * 
+     * @param event
+     *            event to set request for
+     * @return ReplyPacket for setting request
+     */
+    public ReplyPacket setEvent(Event event) {
+        // Create new command packet
+        CommandPacket commandPacket = new CommandPacket(
+                JDWPCommands.EventRequestCommandSet.CommandSetID,
+                JDWPCommands.EventRequestCommandSet.SetCommand);
+
+        // Set eventKind
+        commandPacket.setNextValueAsByte(event.eventKind);
+        // Set suspendPolicy
+        commandPacket.setNextValueAsByte(event.suspendPolicy);
+
+        // Set modifiers
+        commandPacket.setNextValueAsInt(event.modifiers);
+
+        for (int i = 0; i < event.modifiers; i++) {
+
+            commandPacket.setNextValueAsByte(event.mods[i].modKind);
+
+            switch (event.mods[i].modKind) {
+            case EventMod.ModKind.Count: {
+                // Case Count
+                commandPacket.setNextValueAsInt(event.mods[i].count);
+                break;
+            }
+            case EventMod.ModKind.Conditional: {
+                // Case Conditional
+                commandPacket.setNextValueAsInt(event.mods[i].exprID);
+                break;
+            }
+            case EventMod.ModKind.ThreadOnly: {
+                // Case ThreadOnly
+                commandPacket.setNextValueAsThreadID(event.mods[i].thread);
+                break;
+            }
+            case EventMod.ModKind.ClassOnly: {
+                // Case ClassOnly
+                commandPacket
+                        .setNextValueAsReferenceTypeID(event.mods[i].clazz);
+                break;
+            }
+            case EventMod.ModKind.ClassMatch: {
+                // Case ClassMatch
+                commandPacket.setNextValueAsString(event.mods[i].classPattern);
+                break;
+            }
+            case EventMod.ModKind.ClassExclude: {
+                // Case ClassExclude
+                commandPacket.setNextValueAsString(event.mods[i].classPattern);
+                break;
+            }
+            case EventMod.ModKind.LocationOnly: {
+                // Case LocationOnly
+                commandPacket.setNextValueAsLocation(event.mods[i].loc);
+                break;
+            }
+            case EventMod.ModKind.ExceptionOnly:
+                // Case ExceptionOnly
+                commandPacket
+                        .setNextValueAsReferenceTypeID(event.mods[i].exceptionOrNull);
+                commandPacket.setNextValueAsBoolean(event.mods[i].caught);
+                commandPacket.setNextValueAsBoolean(event.mods[i].uncaught);
+                break;
+            case EventMod.ModKind.FieldOnly: {
+                // Case FieldOnly
+                commandPacket
+                        .setNextValueAsReferenceTypeID(event.mods[i].declaring);
+                commandPacket.setNextValueAsFieldID(event.mods[i].fieldID);
+                break;
+            }
+            case EventMod.ModKind.Step: {
+                // Case Step
+                commandPacket.setNextValueAsThreadID(event.mods[i].thread);
+                commandPacket.setNextValueAsInt(event.mods[i].size);
+                commandPacket.setNextValueAsInt(event.mods[i].depth);
+                break;
+            }
+            case EventMod.ModKind.InstanceOnly: {
+                // Case InstanceOnly
+                commandPacket.setNextValueAsObjectID(event.mods[i].instance);
+                break;
+            }
+            }
+        }
+
+        // Send packet
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Gets method reference by signature.
+     * 
+     * @param classReferenceTypeID
+     *            class referenceTypeID.
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket getMethods(long classReferenceTypeID) {
+        // Create new command packet
+        CommandPacket commandPacket = new CommandPacket();
+
+        // Set command. "5" - is ID of Methods command in ReferenceType Command
+        // Set
+        commandPacket
+                .setCommand(JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
+
+        // Set command set. "2" - is ID of ReferenceType Command Set
+        commandPacket
+                .setCommandSet(JDWPCommands.ReferenceTypeCommandSet.CommandSetID);
+
+        // Set outgoing data
+        // Set referenceTypeID
+        commandPacket.setNextValueAsObjectID(classReferenceTypeID);
+
+        // Send packet
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Gets class reference by signature.
+     * 
+     * @param classSignature
+     *            class signature.
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket getClassBySignature(String classSignature) {
+        CommandPacket commandPacket = new CommandPacket(
+                JDWPCommands.VirtualMachineCommandSet.CommandSetID,
+                JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand);
+        commandPacket.setNextValueAsString(classSignature);
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Gets class fields by class referenceTypeID.
+     * 
+     * @param referenceTypeID
+     *            class referenceTypeID.
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket getFieldsInClass(long referenceTypeID) {
+        CommandPacket commandPacket = new CommandPacket(
+                JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
+                JDWPCommands.ReferenceTypeCommandSet.FieldsCommand);
+        commandPacket.setNextValueAsReferenceTypeID(referenceTypeID);
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Sets exception event request for given exception class signature.
+     * 
+     * @param exceptionSignature
+     *            exception signature.
+     * @param caught
+     *            is exception caught
+     * @param uncaught
+     *            is exception uncaught
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setException(String exceptionSignature, boolean caught,
+            boolean uncaught) {
+        // Request referenceTypeID for exception
+        long typeID = getClassID(exceptionSignature);
+        return setException(typeID, caught, uncaught);
+    }
+
+    /**
+     * Sets exception event request for given exception class ID.
+     * 
+     * @param exceptionID
+     *            exception referenceTypeID.
+     * @param caught
+     *            is exception caught
+     * @param uncaught
+     *            is exception uncaught
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setException(long exceptionID, boolean caught,
+            boolean uncaught) {
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.EXCEPTION;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        EventMod[] mods = new EventMod[1];
+        mods[0] = new EventMod();
+        mods[0].modKind = EventMod.ModKind.ExceptionOnly;
+        mods[0].caught = caught;
+        mods[0].uncaught = uncaught;
+        mods[0].exceptionOrNull = exceptionID;
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        return setEvent(event);
+    }
+
+    /**
+     * Sets exception event request for given exception class signature.
+     * 
+     * @param exceptionSignature
+     *            exception signature.
+     * @param caught
+     *            is exception caught
+     * @param uncaught
+     *            is exception uncaught
+     * @param count
+     *            Limit the requested event to be reported at most once after a
+     *            given number of occurrences
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setCountableException(String exceptionSignature,
+            boolean caught, boolean uncaught, int count) {
+        // Request referenceTypeID for exception
+        long exceptionID = getClassID(exceptionSignature);
+        byte eventKind = JDWPConstants.EventKind.EXCEPTION;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        EventMod[] mods = new EventMod[2];
+        mods[0] = new EventMod();
+        mods[0].modKind = EventMod.ModKind.ExceptionOnly;
+        mods[0].caught = caught;
+        mods[0].uncaught = uncaught;
+        mods[0].exceptionOrNull = exceptionID;
+
+        mods[1] = new EventMod();
+        mods[1].modKind = EventMod.ModKind.Count;
+        mods[1].count = count;
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        return setEvent(event);
+    }
+
+    /**
+     * Sets METHOD_ENTRY event request for specified class name pattern.
+     * 
+     * @param classRegexp
+     *            class name pattern or null for no pattern
+     * 
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setMethodEntry(String classRegexp) {
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.METHOD_ENTRY;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        EventMod[] mods = null;
+        if (classRegexp == null) {
+            mods = new EventMod[0];
+        } else {
+            mods = new EventMod[1];
+            mods[0] = new EventMod();
+            mods[0].modKind = EventMod.ModKind.ClassMatch;
+            mods[0].classPattern = classRegexp;
+        }
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        return setEvent(event);
+    }
+
+    /**
+     * Sets METHOD_ENTRY event request for specified class name pattern.
+     * 
+     * @param classRegexp
+     *            class name pattern or null for no pattern
+     * @param count
+     *            Limit the requested event to be reported at most once after a
+     *            given number of occurrences
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setCountableMethodEntry(String classRegexp, int count) {
+        byte eventKind = JDWPConstants.EventKind.METHOD_ENTRY;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        EventMod[] mods = null;
+        if (classRegexp == null) {
+            mods = new EventMod[] { new EventMod() };
+            mods[0].modKind = EventMod.ModKind.Count;
+            mods[0].count = count;
+        } else {
+            mods = new EventMod[2];
+            mods[0] = new EventMod();
+            mods[0].modKind = EventMod.ModKind.ClassMatch;
+            mods[0].classPattern = classRegexp;
+
+            mods[1] = new EventMod();
+            mods[1].modKind = EventMod.ModKind.Count;
+            mods[1].count = count;
+        }
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        return setEvent(event);
+    }
+
+    /**
+     * Sets METHOD_EXIT event request for specified class name pattern.
+     * 
+     * @param classRegexp
+     *            class name pattern or null for no pattern
+     * 
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setMethodExit(String classRegexp) {
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.METHOD_EXIT;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        EventMod[] mods = null;
+        if (classRegexp == null) {
+            mods = new EventMod[0];
+        } else {
+            mods = new EventMod[1];
+            mods[0] = new EventMod();
+            mods[0].modKind = EventMod.ModKind.ClassMatch;
+            mods[0].classPattern = classRegexp;
+        }
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        return setEvent(event);
+    }
+
+    /**
+     * Sets METHOD_EXIT event request for specified class name pattern.
+     * 
+     * @param classRegexp
+     *            classRegexp class name pattern or null for no pattern
+     * @param count
+     *            Limit the requested event to be reported at most once after a
+     *            given number of occurrences
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setCountableMethodExit(String classRegexp, int count) {
+        byte eventKind = JDWPConstants.EventKind.METHOD_EXIT;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        EventMod[] mods = null;
+        if (classRegexp == null) {
+            mods = new EventMod[] { new EventMod() };
+            mods[0].modKind = EventMod.ModKind.Count;
+            mods[0].count = count;
+        } else {
+            mods = new EventMod[2];
+            mods[0] = new EventMod();
+            mods[0].modKind = EventMod.ModKind.ClassMatch;
+            mods[0].classPattern = classRegexp;
+
+            mods[1] = new EventMod();
+            mods[1].modKind = EventMod.ModKind.Count;
+            mods[1].count = count;
+        }
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        return setEvent(event);
+
+    }
+
+    /**
+     * Sets field access event request for specified class signature and field
+     * name.
+     * 
+     * @param classTypeTag
+     *            class Type Tag (class/interface/array)
+     * @param classSignature
+     *            class signature
+     * @param fieldName
+     *            field name
+     * @return ReplyPacket if breakpoint is set
+     * @throws ReplyErrorCodeException
+     */
+    public ReplyPacket setFieldAccess(String classSignature, byte classTypeTag,
+            String fieldName) throws ReplyErrorCodeException {
+        ReplyPacket request = null;
+        long typeID = -1;
+        long fieldID = -1;
+
+        // Request referenceTypeID for class
+        typeID = getClassID(classSignature);
+
+        // Request fields in class
+        request = getFieldsInClass(typeID);
+
+        // Get fieldID from received packet
+        fieldID = getFieldID(request, fieldName);
+
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.FIELD_ACCESS;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        // EventMod[] mods = new EventMod[1];
+        EventMod[] mods = new EventMod[] { new EventMod() };
+        mods[0].fieldID = fieldID;
+        mods[0].declaring = typeID;
+        mods[0].modKind = EventMod.ModKind.FieldOnly;
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        // Set exception
+        return setEvent(event);
+    }
+
+    /**
+     * Sets field modification event request for specified class signature and
+     * field name.
+     * 
+     * @param classTypeTag
+     *            class Type Tag (class/interface/array)
+     * @param classSignature
+     *            class signature
+     * @param fieldName
+     *            field name
+     * @return ReplyPacket for corresponding command
+     * @throws ReplyErrorCodeException
+     */
+    public ReplyPacket setFieldModification(String classSignature,
+            byte classTypeTag, String fieldName) throws ReplyErrorCodeException {
+        ReplyPacket request = null;
+        long typeID = -1;
+        long fieldID = -1;
+
+        // Request referenceTypeID for class
+        typeID = getClassID(classSignature);
+
+        // Request fields in class
+        request = getFieldsInClass(typeID);
+
+        // Get fieldID from received packet
+        fieldID = getFieldID(request, fieldName);
+
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.FIELD_MODIFICATION;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        // EventMod[] mods = new EventMod[1];
+        EventMod[] mods = new EventMod[] { new EventMod() };
+        mods[0].fieldID = fieldID;
+        mods[0].declaring = typeID;
+        mods[0].modKind = EventMod.ModKind.FieldOnly;
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        // Set event
+        return setEvent(event);
+    }
+
+    /**
+     * Sets step event request for given thread name.
+     * 
+     * @param threadName
+     *            thread name
+     * @param stepSize
+     * @param stepDepth
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setStep(String threadName, int stepSize, int stepDepth) {
+        long typeID = -1;
+
+        // Request referenceTypeID for class
+        typeID = getThreadID(threadName);
+
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.SINGLE_STEP;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        // EventMod[] mods = new EventMod[1];
+        EventMod[] mods = new EventMod[] { new EventMod() };
+        mods[0].thread = typeID;
+        mods[0].modKind = EventMod.ModKind.Step;
+        mods[0].size = stepSize;
+        mods[0].depth = stepDepth;
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        // Set event
+        return setEvent(event);
+    }
+
+    /**
+     * Sets SINGLE_STEP event request for classes whose name does not match the
+     * given restricted regular expression
+     * 
+     * @param classRegexp
+     *            Disallowed class patterns. Matches are limited to exact
+     *            matches of the given class pattern and matches of patterns
+     *            that begin or end with '*'; for example, "*.Foo" or "java.*".
+     * @param stepSize
+     * @param stepDepth
+     * @return ReplyPacket for setting request.
+     */
+    public ReplyPacket setStep(String[] classRegexp, long threadID,
+            int stepSize, int stepDepth) {
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.SINGLE_STEP;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        int modsSize = classRegexp.length + 1;
+        EventMod[] mods = new EventMod[modsSize];
+        for (int i = 0; i < classRegexp.length; i++) {
+            mods[i] = new EventMod();
+            mods[i].classPattern = classRegexp[i];
+            mods[i].modKind = EventMod.ModKind.ClassExclude;
+        }
+
+        int index = modsSize - 1;
+        mods[index] = new EventMod();
+        mods[index].modKind = EventMod.ModKind.Step;
+        mods[index].thread = threadID;
+        mods[index].size = stepSize;
+        mods[index].depth = stepDepth;
+
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        // Set event
+        return setEvent(event);
+    }
+
+    /**
+     * Sets THREAD_START event request.
+     * 
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setThreadStart() {
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.THREAD_START;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        EventMod[] mods = new EventMod[0];
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        return setEvent(event);
+    }
+
+    /**
+     * Sets THREAD_END event request.
+     * 
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket setThreadEnd() {
+        // Prepare corresponding event
+        byte eventKind = JDWPConstants.EventKind.THREAD_END;
+        byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL;
+        EventMod[] mods = new EventMod[0];
+        Event event = new Event(eventKind, suspendPolicy, mods);
+
+        return setEvent(event);
+    }
+
+    /**
+     * Clear an event request for specified request ID.
+     * 
+     * @param eventKind
+     *            event type to clear
+     * @param requestID
+     *            request ID to clear
+     * @return ReplyPacket for corresponding command
+     */
+    public ReplyPacket clearEvent(byte eventKind, int requestID) {
+        // Create new command packet
+        CommandPacket commandPacket = new CommandPacket();
+
+        // Set command. "2" - is ID of Clear command in EventRequest Command Set
+        commandPacket
+                .setCommand(JDWPCommands.EventRequestCommandSet.ClearCommand);
+
+        // Set command set. "15" - is ID of EventRequest Command Set
+        commandPacket
+                .setCommandSet(JDWPCommands.EventRequestCommandSet.CommandSetID);
+
+        // Set outgoing data
+        // Set event type to clear
+        commandPacket.setNextValueAsByte(eventKind);
+
+        // Set ID of request to clear
+        commandPacket.setNextValueAsInt(requestID);
+
+        // Send packet
+        return checkReply(performCommand(commandPacket));
+    }
+
+    /**
+     * Sends CommandPacket to debuggee VM and waits for ReplyPacket using
+     * default timeout. All thrown exceptions are wrapped into
+     * TestErrorException. Consider using checkReply() for checking error code
+     * in reply packet.
+     * 
+     * @param command
+     *            Command packet to be sent
+     * @return received ReplyPacket
+     */
+    public ReplyPacket performCommand(CommandPacket command)
+            throws TestErrorException {
+        ReplyPacket replyPacket = null;
+        try {
+            replyPacket = packetDispatcher.performCommand(command);
+        } catch (IOException e) {
+            throw new TestErrorException(e);
+        } catch (InterruptedException e) {
+            throw new TestErrorException(e);
+        }
+
+        return replyPacket;
+    }
+
+    /**
+     * Sends CommandPacket to debuggee VM and waits for ReplyPacket using
+     * specified timeout.
+     * 
+     * @param command
+     *            Command packet to be sent
+     * @param timeout
+     *            Timeout in milliseconds for waiting reply packet
+     * @return received ReplyPacket
+     * @throws InterruptedException
+     * @throws IOException
+     * @throws TimeoutException
+     */
+    public ReplyPacket performCommand(CommandPacket command, long timeout)
+            throws IOException, InterruptedException, TimeoutException {
+
+        return packetDispatcher.performCommand(command, timeout);
+    }
+
+    /**
+     * Sends CommandPacket to debuggee VM without waiting for the reply. This
+     * method is intended for special cases when there is need to divide
+     * command's performing into two actions: command's sending and receiving
+     * reply (e.g. for asynchronous JDWP commands' testing). After this method
+     * the 'receiveReply()' method must be used latter for receiving reply for
+     * sent command. It is NOT recommended to use this method for usual cases -
+     * 'performCommand()' method must be used.
+     * 
+     * @param command
+     *            Command packet to be sent
+     * @return command ID of sent command
+     * @throws IOException
+     *             if any connection error occurred
+     */
+    public int sendCommand(CommandPacket command) throws IOException {
+        return packetDispatcher.sendCommand(command);
+    }
+
+    /**
+     * Waits for reply for command which was sent before by 'sendCommand()'
+     * method. Default timeout is used as time limit for waiting. This method
+     * (jointly with 'sendCommand()') is intended for special cases when there
+     * is need to divide command's performing into two actions: command's
+     * sending and receiving reply (e.g. for asynchronous JDWP commands'
+     * testing). It is NOT recommended to use 'sendCommand()- receiveReply()'
+     * pair for usual cases - 'performCommand()' method must be used.
+     * 
+     * @param commandId
+     *            Command ID of sent before command, reply from which is
+     *            expected to be received
+     * @return received ReplyPacket
+     * @throws IOException
+     *             if any connection error occurred
+     * @throws InterruptedException
+     *             if reply packet's waiting was interrupted
+     * @throws TimeoutException
+     *             if timeout exceeded
+     */
+    public ReplyPacket receiveReply(int commandId) throws InterruptedException,
+            IOException, TimeoutException {
+        return packetDispatcher.receiveReply(commandId, config.getTimeout());
+    }
+
+    /**
+     * Waits for reply for command which was sent before by 'sendCommand()'
+     * method. Specified timeout is used as time limit for waiting. This method
+     * (jointly with 'sendCommand()') is intended for special cases when there
+     * is need to divide command's performing into two actions: command's
+     * sending and receiving reply (e.g. for asynchronous JDWP commands'
+     * testing). It is NOT recommended to use 'sendCommand()- receiveReply()'
+     * pair for usual cases - 'performCommand()' method must be used.
+     * 
+     * @param commandId
+     *            Command ID of sent before command, reply from which is
+     *            expected to be received
+     * @param timeout
+     *            Specified timeout in milliseconds to wait for reply
+     * @return received ReplyPacket
+     * @throws IOException
+     *             if any connection error occurred
+     * @throws InterruptedException
+     *             if reply packet's waiting was interrupted
+     * @throws TimeoutException
+     *             if timeout exceeded
+     */
+    public ReplyPacket receiveReply(int commandId, long timeout)
+            throws InterruptedException, IOException, TimeoutException {
+        return packetDispatcher.receiveReply(commandId, timeout);
+    }
+
+    /**
+     * Waits for EventPacket using default timeout. All thrown exceptions are
+     * wrapped into TestErrorException.
+     * 
+     * @return received EventPacket
+     */
+    public EventPacket receiveEvent() throws TestErrorException {
+        try {
+            return receiveEvent(config.getTimeout());
+        } catch (IOException e) {
+            throw new TestErrorException(e);
+        } catch (InterruptedException e) {
+            throw new TestErrorException(e);
+        }
+    }
+
+    /**
+     * Waits for EventPacket using specified timeout.
+     * 
+     * @param timeout
+     *            Timeout in milliseconds to wait for event
+     * @return received EventPacket
+     * @throws IOException
+     * @throws InterruptedException
+     * @throws TimeoutException
+     */
+    public EventPacket receiveEvent(long timeout) throws IOException,
+            InterruptedException, TimeoutException {
+
+        return packetDispatcher.receiveEvent(timeout);
+    }
+
+    /**
+     * Waits for expected event kind using default timeout. Throws
+     * TestErrorException if received event is not of expected kind or not a
+     * single event in the received event set.
+     * 
+     * @param eventKind
+     *            Type of expected event -
+     * @see JDWPConstants.EventKind
+     * @return received EventPacket
+     */
+    public EventPacket receiveCertainEvent(byte eventKind)
+            throws TestErrorException {
+
+        EventPacket eventPacket = receiveEvent();
+        ParsedEvent[] parsedEvents = ParsedEvent.parseEventPacket(eventPacket);
+
+        if (parsedEvents.length == 1
+                && parsedEvents[0].getEventKind() == eventKind)
+            return eventPacket;
+
+        switch (parsedEvents.length) {
+        case (0):
+            throw new TestErrorException(
+                    "Unexpected event received: zero length");
+        case (1):
+            throw new TestErrorException("Unexpected event received: "
+                    + parsedEvents[0].getEventKind());
+        default:
+            throw new TestErrorException(
+                    "Unexpected event received: Event was grouped in a composite event");
+        }
+    }
+
+    /**
+     * Returns JDWP connection channel used by this VmMirror.
+     * 
+     * @return connection channel
+     */
+    public TransportWrapper getConnection() {
+        return connection;
+    }
+
+    /**
+     * Sets established connection channel to be used with this VmMirror and
+     * starts reading packets.
+     * 
+     * @param connection
+     *            connection channel to be set
+     */
+    public void setConnection(TransportWrapper connection) {
+        this.connection = connection;
+        packetDispatcher = new PacketDispatcher(connection, config, logWriter);
+    }
+
+    /**
+     * Closes connection channel used with this VmMirror and stops reading
+     * packets.
+     * 
+     */
+    public void closeConnection() throws IOException {
+        if (connection != null && connection.isOpen())
+            connection.close();
+
+        // wait for packetDispatcher is closed
+        if (packetDispatcher != null) {
+            try {
+                packetDispatcher.join();
+            } catch (InterruptedException e) {
+                // do nothing but print a stack trace
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * Returns the count of frames on this thread's stack
+     * 
+     * @param threadID
+     *            The thread object ID.
+     * @return The count of frames on this thread's stack
+     */
+    public final int getFrameCount(long threadID) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
+                JDWPCommands.ThreadReferenceCommandSet.FrameCountCommand);
+        command.setNextValueAsThreadID(threadID);
+        ReplyPacket reply = checkReply(performCommand(command));
+        return reply.getNextValueAsInt();
+    }
+
+    /**
+     * Returns a list containing all frames of a certain thread
+     * 
+     * @param threadID
+     *            ID of the thread
+     * @return A list of frames
+     */
+    public final List getAllThreadFrames(long threadID) {
+        if (!isThreadSuspended(threadID)) {
+            return new ArrayList(0);
+        }
+
+        ReplyPacket reply = getThreadFrames(threadID, 0, -1);
+        int framesCount = reply.getNextValueAsInt();
+        if (framesCount == 0) {
+            return new ArrayList(0);
+        }
+
+        ArrayList frames = new ArrayList(framesCount);
+        for (int i = 0; i < framesCount; i++) {
+            Frame frame = new Frame();
+            frame.setThreadID(threadID);
+            frame.setID(reply.getNextValueAsFrameID());
+            frame.setLocation(reply.getNextValueAsLocation());
+            frames.add(frame);
+        }
+
+        return frames;
+    }
+
+    /**
+     * Returns a set of frames of a certain suspended thread
+     * 
+     * @param threadID
+     *            ID of the thread whose frames to obtain
+     * @param startIndex
+     *            The index of the first frame to retrieve.
+     * @param length
+     *            The count of frames to retrieve (-1 means all remaining).
+     * @return ReplyPacket for corresponding command
+     */
+    public final ReplyPacket getThreadFrames(long threadID, int startIndex,
+            int length) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
+                JDWPCommands.ThreadReferenceCommandSet.FramesCommand);
+        command.setNextValueAsThreadID(threadID);
+        command.setNextValueAsInt(startIndex); // start frame's index
+        command.setNextValueAsInt(length); // get all remaining frames;
+        return checkReply(performCommand(command));
+    }
+
+    /**
+     * Returns variable information for the method
+     * 
+     * @param classID
+     *            The class ID
+     * @param methodID
+     *            The method ID
+     * @return A list containing all variables (arguments and locals) declared
+     *         within the method.
+     */
+    public final List getVariableTable(long classID, long methodID) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.MethodCommandSet.CommandSetID,
+                JDWPCommands.MethodCommandSet.VariableTableCommand);
+        command.setNextValueAsReferenceTypeID(classID);
+        command.setNextValueAsMethodID(methodID);
+        // ReplyPacket reply =
+        // debuggeeWrapper.vmMirror.checkReply(debuggeeWrapper.vmMirror.performCommand(command));
+        ReplyPacket reply = performCommand(command);
+        if (reply.getErrorCode() == JDWPConstants.Error.ABSENT_INFORMATION
+                || reply.getErrorCode() == JDWPConstants.Error.NATIVE_METHOD) {
+            return null;
+        }
+
+        checkReply(reply);
+
+        reply.getNextValueAsInt(); // argCnt, is not used
+        int slots = reply.getNextValueAsInt();
+        if (slots == 0) {
+            return null;
+        }
+
+        ArrayList vars = new ArrayList(slots);
+        for (int i = 0; i < slots; i++) {
+            Variable var = new Frame().new Variable();
+            var.setCodeIndex(reply.getNextValueAsLong());
+            var.setName(reply.getNextValueAsString());
+            var.setSignature(reply.getNextValueAsString());
+            var.setLength(reply.getNextValueAsInt());
+            var.setSlot(reply.getNextValueAsInt());
+            vars.add(var);
+        }
+
+        return vars;
+    }
+
+    /**
+     * Returns values of local variables in a given frame
+     * 
+     * @param frame
+     *            Frame whose variables to get
+     * @return An array of Value objects
+     */
+    public final Value[] getFrameValues(Frame frame) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.StackFrameCommandSet.CommandSetID,
+                JDWPCommands.StackFrameCommandSet.GetValuesCommand);
+        command.setNextValueAsThreadID(frame.getThreadID());
+        command.setNextValueAsFrameID(frame.getID());
+        int slots = frame.getVars().size();
+        command.setNextValueAsInt(slots);
+        Iterator it = frame.getVars().iterator();
+        while (it.hasNext()) {
+            Frame.Variable var = (Frame.Variable) it.next();
+            command.setNextValueAsInt(var.getSlot());
+            command.setNextValueAsByte(var.getTag());
+        }
+
+        ReplyPacket reply = checkReply(performCommand(command));
+        reply.getNextValueAsInt(); // number of values , is not used
+        Value[] values = new Value[slots];
+        for (int i = 0; i < slots; i++) {
+            values[i] = reply.getNextValueAsValue();
+        }
+
+        return values;
+    }
+
+    /**
+     * Returns the immediate superclass of a class
+     * 
+     * @param classID
+     *            The class ID whose superclass ID is to get
+     * @return The superclass ID (null if the class ID for java.lang.Object is
+     *         specified).
+     */
+    public final long getSuperclassId(long classID) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.ClassTypeCommandSet.CommandSetID,
+                JDWPCommands.ClassTypeCommandSet.SuperclassCommand);
+        command.setNextValueAsClassID(classID);
+        ReplyPacket reply = checkReply(performCommand(command));
+        return reply.getNextValueAsClassID();
+    }
+
+    /**
+     * Returns the runtime type of the object
+     * 
+     * @param objectID
+     *            The object ID
+     * @return The runtime reference type.
+     */
+    public final long getReferenceType(long objectID) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
+                JDWPCommands.ObjectReferenceCommandSet.ReferenceTypeCommand);
+        command.setNextValueAsObjectID(objectID);
+        ReplyPacket reply = checkReply(performCommand(command));
+        reply.getNextValueAsByte();
+        return reply.getNextValueAsLong();
+    }
+
+    /**
+     * Returns the class object corresponding to this type
+     * 
+     * @param refType
+     *            The reference type ID.
+     * @return The class object.
+     */
+    public final long getClassObjectId(long refType) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
+                JDWPCommands.ReferenceTypeCommandSet.ClassObjectCommand);
+        command.setNextValueAsReferenceTypeID(refType);
+        ReplyPacket reply = checkReply(performCommand(command));
+        return reply.getNextValueAsObjectID();
+    }
+
+    /**
+     * Returns line number information for the method, if present.
+     * 
+     * @param refType
+     *            The class ID
+     * @param methodID
+     *            The method ID
+     * @return ReplyPacket for corresponding command.
+     */
+    public final ReplyPacket getLineTable(long refType, long methodID) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.MethodCommandSet.CommandSetID,
+                JDWPCommands.MethodCommandSet.LineTableCommand);
+        command.setNextValueAsReferenceTypeID(refType);
+        command.setNextValueAsMethodID(methodID);
+        // ReplyPacket reply =
+        // debuggeeWrapper.vmMirror.checkReply(debuggeeWrapper.vmMirror.performCommand(command));
+        // it is impossible to obtain line table information from native
+        // methods, so reply checking is not performed
+        ReplyPacket reply = performCommand(command);
+        if (reply.getErrorCode() != JDWPConstants.Error.NONE) {
+            if (reply.getErrorCode() == JDWPConstants.Error.NATIVE_METHOD) {
+                return reply;
+            }
+        }
+
+        return checkReply(reply);
+    }
+
+    /**
+     * Returns the value of one or more instance fields.
+     * 
+     * @param objectID
+     *            The object ID
+     * @param fieldIDs
+     *            IDs of fields to get
+     * @return An array of Value objects representing each field's value
+     */
+    public final Value[] getObjectReferenceValues(long objectID, long[] fieldIDs) {
+        int fieldsCount = fieldIDs.length;
+        if (fieldsCount == 0) {
+            return null;
+        }
+
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.ObjectReferenceCommandSet.CommandSetID,
+                JDWPCommands.ObjectReferenceCommandSet.GetValuesCommand);
+        command.setNextValueAsReferenceTypeID(objectID);
+        command.setNextValueAsInt(fieldsCount);
+        for (int i = 0; i < fieldsCount; i++) {
+            command.setNextValueAsFieldID(fieldIDs[i]);
+        }
+
+        ReplyPacket reply = checkReply(performCommand(command));
+        reply.getNextValueAsInt(); // fields returned, is not used
+        Value[] values = new Value[fieldsCount];
+        for (int i = 0; i < fieldsCount; i++) {
+            values[i] = reply.getNextValueAsValue();
+        }
+
+        return values;
+    }
+
+    /**
+     * Returns the value of one or more static fields of the reference type
+     * 
+     * @param refTypeID
+     *            The reference type ID.
+     * @param fieldIDs
+     *            IDs of fields to get
+     * @return An array of Value objects representing each field's value
+     */
+    public final Value[] getReferenceTypeValues(long refTypeID, long[] fieldIDs) {
+        int fieldsCount = fieldIDs.length;
+        if (fieldsCount == 0) {
+            return null;
+        }
+
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
+                JDWPCommands.ReferenceTypeCommandSet.GetValuesCommand);
+        command.setNextValueAsReferenceTypeID(refTypeID);
+        command.setNextValueAsInt(fieldsCount);
+        for (int i = 0; i < fieldsCount; i++) {
+            command.setNextValueAsFieldID(fieldIDs[i]);
+        }
+
+        ReplyPacket reply = checkReply(performCommand(command));
+        reply.getNextValueAsInt(); // fields returned, is not used
+        Value[] values = new Value[fieldsCount];
+        for (int i = 0; i < fieldsCount; i++) {
+            values[i] = reply.getNextValueAsValue();
+        }
+
+        return values;
+    }
+
+    /**
+     * Returns the value of the 'this' reference for this frame
+     * 
+     * @param threadID
+     *            The frame's thread ID
+     * @param frameID
+     *            The frame ID.
+     * @return The 'this' object ID for this frame.
+     */
+    public final long getThisObject(long threadID, long frameID) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.StackFrameCommandSet.CommandSetID,
+                JDWPCommands.StackFrameCommandSet.ThisObjectCommand);
+        command.setNextValueAsThreadID(threadID);
+        command.setNextValueAsFrameID(frameID);
+        ReplyPacket reply = checkReply(performCommand(command));
+        TaggedObject taggedObject = reply.getNextValueAsTaggedObject();
+        return taggedObject.objectID;
+    }
+
+    /**
+     * Returns information for each field in a reference type including
+     * inherited fields
+     * 
+     * @param classID
+     *            The reference type ID
+     * @return A list of Field objects representing each field of the class
+     */
+    public final List getAllFields(long classID) {
+        ArrayList fields = new ArrayList(0);
+
+        long superID = getSuperclassId(classID);
+        if (superID != 0) {
+            List superClassFields = getAllFields(superID);
+            for (int i = 0; i < superClassFields.size(); i++) {
+                fields.add(superClassFields.toArray()[i]);
+            }
+        }
+
+        ReplyPacket reply = getFieldsInClass(classID);
+        int fieldsCount = reply.getNextValueAsInt();
+        for (int i = 0; i < fieldsCount; i++) {
+            Field field = new Field(reply.getNextValueAsFieldID(), classID,
+                    reply.getNextValueAsString(), reply.getNextValueAsString(),
+                    reply.getNextValueAsInt());
+            fields.add(field);
+        }
+
+        return fields;
+    }
+
+    /**
+     * Returns the reference type reflected by this class object
+     * 
+     * @param classObjectID
+     *            The class object ID.
+     * @return ReplyPacket for corresponding command
+     */
+    public final ReplyPacket getReflectedType(long classObjectID) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.ClassObjectReferenceCommandSet.CommandSetID,
+                JDWPCommands.ClassObjectReferenceCommandSet.ReflectedTypeCommand);
+        command.setNextValueAsClassObjectID(classObjectID);
+        return checkReply(performCommand(command));
+    }
+
+    /**
+     * Returns the JNI signature of a reference type. JNI signature formats are
+     * described in the Java Native Interface Specification
+     * 
+     * @param refTypeID
+     *            The reference type ID.
+     * @return The JNI signature for the reference type.
+     */
+    public final String getReferenceTypeSignature(long refTypeID) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
+                JDWPCommands.ReferenceTypeCommandSet.SignatureCommand);
+        command.setNextValueAsReferenceTypeID(refTypeID);
+        ReplyPacket reply = checkReply(performCommand(command));
+        return reply.getNextValueAsString();
+    }
+
+    /**
+     * Returns the thread group that contains a given thread
+     * 
+     * @param threadID
+     *            The thread object ID.
+     * @return The thread group ID of this thread.
+     */
+    public final long getThreadGroupID(long threadID) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
+                JDWPCommands.ThreadReferenceCommandSet.ThreadGroupCommand);
+        command.setNextValueAsThreadID(threadID);
+        ReplyPacket reply = checkReply(performCommand(command));
+        return reply.getNextValueAsThreadGroupID();
+    }
+
+    /**
+     * Checks whether a given thread is suspended or not
+     * 
+     * @param threadID
+     *            The thread object ID.
+     * @return True if a given thread is suspended, false otherwise.
+     */
+    public final boolean isThreadSuspended(long threadID) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
+                JDWPCommands.ThreadReferenceCommandSet.StatusCommand);
+        command.setNextValueAsThreadID(threadID);
+        ReplyPacket reply = checkReply(performCommand(command));
+        reply.getNextValueAsInt(); // the thread's status; is not used
+        return reply.getNextValueAsInt() == JDWPConstants.SuspendStatus.SUSPEND_STATUS_SUSPENDED;
+    }
+
+    /**
+     * Returns JNI signature of method.
+     * 
+     * @param classID
+     *            The reference type ID.
+     * @param methodID
+     *            The method ID.
+     * @return JNI signature of method.
+     */
+    public final String getMethodSignature(long classID, long methodID) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
+                JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
+        command.setNextValueAsReferenceTypeID(classID);
+        ReplyPacket reply = checkReply(performCommand(command));
+        int methods = reply.getNextValueAsInt();
+        String value = null;
+        for (int i = 0; i < methods; i++) {
+            long mID = reply.getNextValueAsMethodID();
+            reply.getNextValueAsString(); // name of the method; is not used
+            String methodSign = reply.getNextValueAsString();
+            reply.getNextValueAsInt();
+            if (mID == methodID) {
+                value = methodSign;
+                value = value.replaceAll("/", ".");
+                int lastRoundBracketIndex = value.lastIndexOf(")");
+                value = value.substring(0, lastRoundBracketIndex + 1);
+                break;
+            }
+        }
+
+        return value;
+    }
+
+    /**
+     * Returns the characters contained in the string
+     * 
+     * @param objectID
+     *            The String object ID.
+     * @return A string value.
+     */
+    public final String getStringValue(long objectID) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.StringReferenceCommandSet.CommandSetID,
+                JDWPCommands.StringReferenceCommandSet.ValueCommand);
+        command.setNextValueAsObjectID(objectID);
+        ReplyPacket reply = checkReply(performCommand(command));
+        return reply.getNextValueAsString();
+    }
+
+    /**
+     * Returns a range of array components
+     * 
+     * @param objectID
+     *            The array object ID.
+     * @return The retrieved values.
+     */
+    public Value[] getArrayValues(long objectID) {
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.ArrayReferenceCommandSet.CommandSetID,
+                JDWPCommands.ArrayReferenceCommandSet.LengthCommand);
+        command.setNextValueAsArrayID(objectID);
+        ReplyPacket reply = checkReply(performCommand(command));
+        int length = reply.getNextValueAsInt();
+
+        if (length == 0) {
+            return null;
+        }
+
+        command = new CommandPacket(
+                JDWPCommands.ArrayReferenceCommandSet.CommandSetID,
+                JDWPCommands.ArrayReferenceCommandSet.GetValuesCommand);
+        command.setNextValueAsArrayID(objectID);
+        command.setNextValueAsInt(0);
+        command.setNextValueAsInt(length);
+        reply = checkReply(performCommand(command));
+        ArrayRegion arrayRegion = reply.getNextValueAsArrayRegion();
+
+        Value[] values = new Value[length];
+        for (int i = 0; i < length; i++) {
+            values[i] = arrayRegion.getValue(i);
+        }
+
+        return values;
+    }
+
+    /**
+     * Returns a source line number according to a corresponding line code index
+     * in a method's line table.
+     * 
+     * @param classID
+     *            The class object ID.
+     * @param methodID
+     *            The method ID.
+     * @param codeIndex
+     *            The line code index.
+     * @return An integer line number.
+     */
+    public final int getLineNumber(long classID, long methodID, long codeIndex) {
+        int lineNumber = -1;
+        ReplyPacket reply = getLineTable(classID, methodID);
+        if (reply.getErrorCode() != JDWPConstants.Error.NONE) {
+            return lineNumber;
+        }
+
+        reply.getNextValueAsLong(); // start line index, is not used
+        reply.getNextValueAsLong(); // end line index, is not used
+        int lines = reply.getNextValueAsInt();
+        for (int i = 0; i < lines; i++) {
+            long lineCodeIndex = reply.getNextValueAsLong();
+            lineNumber = reply.getNextValueAsInt();
+            if (lineCodeIndex == codeIndex) {
+                break;
+            }
+
+            if (lineCodeIndex > codeIndex) {
+                --lineNumber;
+                break;
+            }
+        }
+
+        return lineNumber;
+    }
+
+    /**
+     * Returns a line code index according to a corresponding line number in a
+     * method's line table.
+     * 
+     * @param classID
+     *            The class object ID.
+     * @param methodID
+     *            The method ID.
+     * @param lineNumber
+     *            A source line number.
+     * @return An integer representing the line code index.
+     */
+    public final long getLineCodeIndex(long classID, long methodID,
+            int lineNumber) {
+        ReplyPacket reply = getLineTable(classID, methodID);
+        if (reply.getErrorCode() != JDWPConstants.Error.NONE) {
+            return -1L;
+        }
+
+        reply.getNextValueAsLong(); // start line index, is not used
+        reply.getNextValueAsLong(); // end line index, is not used
+        int lines = reply.getNextValueAsInt();
+        for (int i = 0; i < lines; i++) {
+            long lineCodeIndex = reply.getNextValueAsLong();
+            if (lineNumber == reply.getNextValueAsInt()) {
+                return lineCodeIndex;
+            }
+        }
+
+        return -1L;
+    }
+
+    /**
+     * Returns all variables which are visible within the given frame.
+     * 
+     * @param frame
+     *            The frame whose visible local variables to retrieve.
+     * @return A list of Variable objects representing each visible local
+     *         variable within the given frame.
+     */
+    public final List getLocalVars(Frame frame) {
+        List vars = getVariableTable(frame.getLocation().classID, frame
+                .getLocation().methodID);
+        if (vars == null) {
+            return null;
+        }
+
+        // All variables that are not visible from within current frame must be
+        // removed from the list
+        long frameCodeIndex = frame.getLocation().index;
+        for (int i = 0; i < vars.size(); i++) {
+            Variable var = (Variable) vars.toArray()[i];
+            long varCodeIndex = var.getCodeIndex();
+            if (varCodeIndex > frameCodeIndex
+                    || (frameCodeIndex >= varCodeIndex + var.getLength())) {
+                vars.remove(i);
+                --i;
+                continue;
+            }
+        }
+
+        return vars;
+    }
+
+    /**
+     * Sets the value of one or more local variables
+     * 
+     * @param frame
+     *            The frame ID.
+     * @param vars
+     *            An array of Variable objects whose values to set
+     * @param values
+     *            An array of Value objects to set
+     */
+    public final void setLocalVars(Frame frame, Variable[] vars, Value[] values) {
+        if (vars.length != values.length) {
+            throw new TestErrorException(
+                    "Number of variables doesn't correspond to number of their values");
+        }
+
+        CommandPacket command = new CommandPacket(
+                JDWPCommands.StackFrameCommandSet.CommandSetID,
+                JDWPCommands.StackFrameCommandSet.SetValuesCommand);
+        command.setNextValueAsThreadID(frame.getThreadID());
+        command.setNextValueAsFrameID(frame.getID());
+        command.setNextValueAsInt(vars.length);
+        for (int i = 0; i < vars.length; i++) {
+            command.setNextValueAsInt(vars[i].getSlot());
+            command.setNextValueAsValue(values[i]);
+        }
+
+        checkReply(performCommand(command));
+    }
+
+    /**
+     * Sets the value of one or more instance fields
+     * 
+     * @param objectID
+     *            The object ID.
+     * @param fieldIDs
+     *            An array of fields IDs
+     * @param values
+     *            An array of Value objects representing each value to set
+     */

[... 176 lines stripped ...]