| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 |
| */ |
| |
| 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 int setBreakpointAtMethodBegin(long classID, String methodName) { |
| return setBreakpointAtMethodBegin(classID, methodName, JDWPConstants.SuspendPolicy.ALL); |
| } |
| |
| /** |
| * 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 int setBreakpointAtMethodBegin(long classID, String methodName, byte suspendPolicy) { |
| 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, suspendPolicy); |
| checkReply(reply); |
| |
| return reply.getNextValueAsInt(); |
| } |
| |
| /** |
| * 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(int 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.canGetInstanceInfo = replyPacket |
| .getNextValueAsBoolean(); |
| targetVMCapabilities.reserved17 = replyPacket.getNextValueAsBoolean(); |
| targetVMCapabilities.canGetMonitorFrameInfo = replyPacket |
| .getNextValueAsBoolean(); |
| targetVMCapabilities.canUseSourceNameFilters = replyPacket.getNextValueAsBoolean(); |
| targetVMCapabilities.canGetConstantPool = replyPacket |
| .getNextValueAsBoolean(); |
| targetVMCapabilities.canForceEarlyReturn = 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; |
| } |
| |
| public boolean canWatchFieldModification() { |
| capabilities(); |
| return targetVMCapabilities.canWatchFieldModification; |
| } |
| |
| public boolean canWatchFieldAccess() { |
| capabilities(); |
| return targetVMCapabilities.canWatchFieldAccess; |
| } |
| |
| public boolean canUseInstanceFilters() { |
| capabilities(); |
| return targetVMCapabilities.canUseInstanceFilters; |
| } |
| |
| /** |
| * 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 suspend count for specified <code>threadID</code>. |
| * |
| * @param threadID |
| * thread ID |
| * @return thread's suspend count |
| */ |
| public int getThreadSuspendCount(long threadID) { |
| CommandPacket commandPacket = new CommandPacket( |
| JDWPCommands.ThreadReferenceCommandSet.CommandSetID, |
| JDWPCommands.ThreadReferenceCommandSet.SuspendCountCommand); |
| 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 ClassPrepare event request for given source name pattern. |
| * |
| * @param sourceNamePattern |
| * Required source name pattern. Matches are limited to exact matches |
| * of the given source name pattern and matches of patterns that begin |
| * or end with '*'; for example, "*.Foo" or "java.*". |
| * @return ReplyPacket for setting request. |
| */ |
| public ReplyPacket setClassPreparedForSourceNameMatch(String sourceNamePattern) { |
| // Prepare corresponding event |
| byte eventKind = JDWPConstants.EventKind.CLASS_PREPARE; |
| byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; |
| EventMod[] mods = new EventMod[] { new EventMod() }; |
| mods[0].sourceNamePattern = sourceNamePattern; |
| mods[0].modKind = EventMod.ModKind.SourceNameMatch; |
| Event event = new Event(eventKind, suspendPolicy, mods); |
| |
| // Set event |
| return setEvent(event); |
| } |
| |
| /** |
| * Sets ClassUnload event request for given class name pattern. |
| * |
| * @param classSignature |
| * class signature |
| * @return ReplyPacket for setting request |
| */ |
| public ReplyPacket setClassUnload(String classRegexp) { |
| // 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].classPattern = classRegexp; |
| mods[0].modKind = EventMod.ModKind.ClassMatch; |
| Event event = new Event(eventKind, suspendPolicy, mods); |
| |
| // Set event |
| return setEvent(event); |
| } |
| |
| /** |
| * 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 MonitorContendedEnter event request for given class's reference type |
| * |
| * @param referenceTypeID |
| * class referenceTypeID |
| * @return ReplyPacket for setting request |
| */ |
| public ReplyPacket setMonitorContendedEnterForClassOnly(long referenceTypeID) { |
| // Prepare corresponding event |
| byte eventKind = JDWPConstants.EventKind.MONITOR_CONTENDED_ENTER; |
| 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); |
| } |
| |
| public ReplyPacket setMonitorContendedEnterForClassMatch(String classRegexp) { |
| // Prepare corresponding event |
| byte eventKind = JDWPConstants.EventKind.MONITOR_CONTENDED_ENTER; |
| byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; |
| 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 MonitorContendedEntered event request for given class's reference type |
| * |
| * @param referenceTypeID |
| * class referenceTypeID |
| * @return ReplyPacket for setting request |
| */ |
| public ReplyPacket setMonitorContendedEnteredForClassOnly(long referenceTypeID) { |
| // Prepare corresponding event |
| byte eventKind = JDWPConstants.EventKind.MONITOR_CONTENDED_ENTERED; |
| 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); |
| } |
| |
| public ReplyPacket setMonitorContendedEnteredForClassMatch(String classRegexp) { |
| // Prepare corresponding event |
| byte eventKind = JDWPConstants.EventKind.MONITOR_CONTENDED_ENTERED; |
| byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; |
| 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 MonitorWait event request for given class's reference type |
| * |
| * @param referenceTypeID |
| * class referenceTypeID |
| * @return ReplyPacket for setting request |
| */ |
| public ReplyPacket setMonitorWaitForClassOnly(long referenceTypeID) { |
| // Prepare corresponding event |
| byte eventKind = JDWPConstants.EventKind.MONITOR_WAIT; |
| 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 MonitorWait event request for given 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 setMonitorWaitForClassMatch(String classRegexp) { |
| // Prepare corresponding event |
| byte eventKind = JDWPConstants.EventKind.MONITOR_WAIT; |
| byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; |
| 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 MonitorWait event request for classes |
| * whose name does not match the given restricted regular expression. |
| * |
| * @param classRegexp |
| * Exclude 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 setMonitorWaitForClassExclude (String classRegexp) { |
| // Prepare corresponding event |
| byte eventKind = JDWPConstants.EventKind.MONITOR_WAIT; |
| byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; |
| EventMod[] mods = new EventMod[] { new EventMod() }; |
| mods[0].classPattern = classRegexp; |
| mods[0].modKind = EventMod.ModKind.ClassExclude; |
| Event event = new Event(eventKind, suspendPolicy, mods); |
| |
| // Set event |
| return setEvent(event); |
| } |
| |
| /** |
| * Set MonitorWaited event request for given class's reference type |
| * |
| * @param referenceTypeID |
| * class referenceTypeID |
| * @return ReplyPacket for setting request |
| */ |
| public ReplyPacket setMonitorWaitedForClassOnly(long referenceTypeID) { |
| // Prepare corresponding event |
| byte eventKind = JDWPConstants.EventKind.MONITOR_WAITED; |
| 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 MonitorWaited event request for given given source 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 setMonitorWaitedForClassMatch(String classRegexp) { |
| // Prepare corresponding event |
| byte eventKind = JDWPConstants.EventKind.MONITOR_WAITED; |
| byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; |
| 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 MonitorWaited event request for classes |
| * whose name does not match the given restricted regular expression. |
| * |
| * @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 setMonitorWaitedForClassExclude (String classRegexp) { |
| // Prepare corresponding event |
| byte eventKind = JDWPConstants.EventKind.MONITOR_WAITED; |
| byte suspendPolicy = JDWPConstants.SuspendPolicy.ALL; |
| EventMod[] mods = new EventMod[] { new EventMod() }; |
| mods[0].classPattern = classRegexp; |
| mods[0].modKind = EventMod.ModKind.ClassExclude; |
| 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; |
| } |
| case EventMod.ModKind.SourceNameMatch: { |
| // Case SourceNameMatch |
| commandPacket.setNextValueAsString(event.mods[i].sourceNamePattern); |
| } |
| } |
| } |
| |
| // 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_WITH_RETURN_VALUE event request for specified class name pattern. |
| * |
| * @param classRegexp |
| * class name pattern or null for no pattern |
| * |
| * @return ReplyPacket for corresponding command |
| */ |
| public ReplyPacket setMethodExitWithReturnValue(String classRegexp) { |
| // Prepare corresponding event |
| byte eventKind = JDWPConstants.EventKind.METHOD_EXIT_WITH_RETURN_VALUE; |
| 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<Frame> frames = new ArrayList<Frame>(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<Variable> vars = new ArrayList<Variable>(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 one static field of the reference type |
| * |
| * @param refTypeID |
| * The reference type ID. |
| * @param fieldID |
| * ID of field to get |
| * @return A Value object representing the field's value |
| */ |
| public final Value getReferenceTypeValue(long refTypeID, long fieldID) { |
| Value[] values = getReferenceTypeValues(refTypeID, new long[]{fieldID}); |
| return values[0]; |
| } |
| |
| /** |
| * 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<Field> fields = new ArrayList<Field>(0); |
| |
| long superID = getSuperclassId(classID); |
| if (superID != 0) { |
| List superClassFields = getAllFields(superID); |
| for (int i = 0; i < superClassFields.size(); i++) { |
| fields.add((Field) 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 |
| */ |
| public final void setInstanceFieldsValues(long objectID, long[] fieldIDs, |
| Value[] values) { |
| if (fieldIDs.length != values.length) { |
| throw new TestErrorException( |
| "Number of fields doesn't correspond to number of their values"); |
| } |
| |
| CommandPacket command = new CommandPacket( |
| JDWPCommands.ObjectReferenceCommandSet.CommandSetID, |
| JDWPCommands.ObjectReferenceCommandSet.SetValuesCommand); |
| command.setNextValueAsObjectID(objectID); |
| command.setNextValueAsInt(fieldIDs.length); |
| for (int i = 0; i < fieldIDs.length; i++) { |
| command.setNextValueAsFieldID(fieldIDs[i]); |
| command.setNextValueAsUntaggedValue(values[i]); |
| } |
| |
| checkReply(performCommand(command)); |
| } |
| |
| /** |
| * Sets a range of array components. The specified range must be within the |
| * bounds of the array. |
| * |
| * @param arrayID |
| * The array object ID. |
| * @param firstIndex |
| * The first index to set. |
| * @param values |
| * An array of Value objects representing each value to set. |
| */ |
| public final void setArrayValues(long arrayID, int firstIndex, |
| Value[] values) { |
| CommandPacket command = new CommandPacket( |
| JDWPCommands.ArrayReferenceCommandSet.CommandSetID, |
| JDWPCommands.ArrayReferenceCommandSet.SetValuesCommand); |
| command.setNextValueAsArrayID(arrayID); |
| command.setNextValueAsInt(firstIndex); |
| command.setNextValueAsInt(values.length); |
| for (int i = 0; i < values.length; i++) { |
| command.setNextValueAsUntaggedValue(values[i]); |
| } |
| |
| checkReply(performCommand(command)); |
| } |
| |
| /** |
| * Sets the value of one or more static fields |
| * |
| * @param classID |
| * The class type ID. |
| * @param fieldIDs |
| * An array of fields IDs |
| * @param values |
| * An array of Value objects representing each value to set |
| */ |
| public final void setStaticFieldsValues(long classID, long[] fieldIDs, |
| Value[] values) { |
| if (fieldIDs.length != values.length) { |
| throw new TestErrorException( |
| "Number of fields doesn't correspond to number of their values"); |
| } |
| |
| CommandPacket command = new CommandPacket( |
| JDWPCommands.ClassTypeCommandSet.CommandSetID, |
| JDWPCommands.ClassTypeCommandSet.SetValuesCommand); |
| command.setNextValueAsClassID(classID); |
| command.setNextValueAsInt(fieldIDs.length); |
| for (int i = 0; i < fieldIDs.length; i++) { |
| command.setNextValueAsFieldID(fieldIDs[i]); |
| command.setNextValueAsUntaggedValue(values[i]); |
| } |
| |
| checkReply(performCommand(command)); |
| } |
| |
| /** |
| * Creates java String in target VM with the given value. |
| * |
| * @param value |
| * The value of the string. |
| * @return The string id. |
| */ |
| public final long createString(String value) { |
| CommandPacket command = new CommandPacket( |
| JDWPCommands.VirtualMachineCommandSet.CommandSetID, |
| JDWPCommands.VirtualMachineCommandSet.CreateStringCommand); |
| command.setNextValueAsString(value); |
| ReplyPacket reply = checkReply(performCommand(command)); |
| return reply.getNextValueAsStringID(); |
| } |
| |
| /** |
| * Processes JDWP PopFrames command from StackFrame command set. |
| * |
| * @param frame |
| * The instance of Frame. |
| */ |
| public final void popFrame(Frame frame) { |
| CommandPacket command = new CommandPacket( |
| JDWPCommands.StackFrameCommandSet.CommandSetID, |
| JDWPCommands.StackFrameCommandSet.PopFramesCommand); |
| command.setNextValueAsThreadID(frame.getThreadID()); |
| command.setNextValueAsFrameID(frame.getID()); |
| checkReply(performCommand(command)); |
| } |
| |
| /** |
| * Invokes a member method of the given object. |
| * |
| * @param objectID |
| * The object ID. |
| * @param threadID |
| * The thread ID. |
| * @param methodName |
| * The name of method for the invocation. |
| * @param args |
| * The arguments for the invocation. |
| * @param options |
| * The invocation options. |
| * @return ReplyPacket for corresponding command |
| */ |
| public final ReplyPacket invokeInstanceMethod(long objectID, long threadID, |
| String methodName, Value[] args, int options) { |
| long classID = getReferenceType(objectID); |
| long methodID = getMethodID(classID, methodName); |
| CommandPacket command = new CommandPacket( |
| JDWPCommands.ObjectReferenceCommandSet.CommandSetID, |
| JDWPCommands.ObjectReferenceCommandSet.InvokeMethodCommand); |
| command.setNextValueAsObjectID(objectID); |
| command.setNextValueAsThreadID(threadID); |
| command.setNextValueAsClassID(classID); |
| command.setNextValueAsMethodID(methodID); |
| command.setNextValueAsInt(args.length); |
| for (int i = 0; i < args.length; i++) { |
| command.setNextValueAsValue(args[i]); |
| } |
| command.setNextValueAsInt(options); |
| |
| return checkReply(performCommand(command)); |
| } |
| |
| /** |
| * Invokes a static method of the given class. |
| * |
| * @param classID |
| * The class type ID. |
| * @param threadID |
| * The thread ID. |
| * @param methodName |
| * The name of method for the invocation. |
| * @param args |
| * The arguments for the invocation. |
| * @param options |
| * The invocation options. |
| * @return ReplyPacket for corresponding command |
| */ |
| public final ReplyPacket invokeStaticMethod(long classID, long threadID, |
| String methodName, Value[] args, int options) { |
| long methodID = getMethodID(classID, methodName); |
| CommandPacket command = new CommandPacket( |
| JDWPCommands.ClassTypeCommandSet.CommandSetID, |
| JDWPCommands.ClassTypeCommandSet.InvokeMethodCommand); |
| command.setNextValueAsClassID(classID); |
| command.setNextValueAsThreadID(threadID); |
| command.setNextValueAsMethodID(methodID); |
| command.setNextValueAsInt(args.length); |
| for (int i = 0; i < args.length; i++) { |
| command.setNextValueAsValue(args[i]); |
| } |
| command.setNextValueAsInt(options); |
| |
| return checkReply(performCommand(command)); |
| } |
| } |