| /******************************************************************************* |
| * Copyright (c) 2000, 2015 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdi.internal; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.DataInputStream; |
| import java.io.DataOutputStream; |
| import java.io.IOException; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.Modifier; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.jdi.Bootstrap; |
| import org.eclipse.jdi.internal.connect.PacketReceiveManager; |
| import org.eclipse.jdi.internal.connect.PacketSendManager; |
| import org.eclipse.jdi.internal.event.EventQueueImpl; |
| import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket; |
| import org.eclipse.jdi.internal.jdwp.JdwpObjectID; |
| import org.eclipse.jdi.internal.jdwp.JdwpReferenceTypeID; |
| import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket; |
| import org.eclipse.jdi.internal.request.EventRequestManagerImpl; |
| import org.eclipse.osgi.util.NLS; |
| |
| import com.sun.jdi.BooleanValue; |
| import com.sun.jdi.ByteValue; |
| import com.sun.jdi.CharValue; |
| import com.sun.jdi.DoubleValue; |
| import com.sun.jdi.FloatValue; |
| import com.sun.jdi.IntegerValue; |
| import com.sun.jdi.LongValue; |
| import com.sun.jdi.ObjectCollectedException; |
| import com.sun.jdi.ReferenceType; |
| import com.sun.jdi.ShortValue; |
| import com.sun.jdi.StringReference; |
| import com.sun.jdi.ThreadGroupReference; |
| import com.sun.jdi.ThreadReference; |
| import com.sun.jdi.VMDisconnectedException; |
| import com.sun.jdi.VirtualMachine; |
| import com.sun.jdi.VoidValue; |
| import com.sun.jdi.connect.spi.Connection; |
| import com.sun.jdi.event.EventQueue; |
| import com.sun.jdi.request.EventRequestManager; |
| |
| /** |
| * This class implements the corresponding interfaces declared by the JDI |
| * specification. See the com.sun.jdi package for more information. |
| * |
| */ |
| public class VirtualMachineImpl extends MirrorImpl implements VirtualMachine, |
| org.eclipse.jdi.hcr.VirtualMachine, org.eclipse.jdi.VirtualMachine { |
| /** Result flags for Classes Have Changed command. */ |
| public static final byte HCR_RELOAD_SUCCESS = 0; |
| public static final byte HCR_RELOAD_FAILURE = 1; |
| public static final byte HCR_RELOAD_IGNORED = 2; |
| |
| /* Indexes in HCR capabilities list. */ |
| private static final int HCR_CAN_RELOAD_CLASSES = 0; |
| private static final int HCR_CAN_GET_CLASS_VERSION = 1; |
| private static final int HCR_CAN_DO_RETURN = 2; |
| private static final int HCR_CAN_REENTER_ON_EXIT = 3; |
| |
| protected static final String JAVA_STRATUM_NAME = "Java"; //$NON-NLS-1$ |
| |
| /** Timeout value for requests to VM if not overridden for a particular VM. */ |
| private int fRequestTimeout; |
| /** Mapping of command codes to strings. */ |
| |
| private static Map<Integer, String> fgHCRResultMap = null; |
| |
| /** EventRequestManager that creates event objects on request. */ |
| private EventRequestManagerImpl fEventReqMgr; |
| /** EventQueue that returns EventSets from the Virtual Manager. */ |
| private EventQueueImpl fEventQueue; |
| |
| /** If a launching connector is used, we store the process. */ |
| private Process fLaunchedProcess; |
| |
| /** |
| * The following field contains cached Mirrors. Note that these are |
| * optional: their only purpose is to speed up the debugger by being able to |
| * use the stored results of JDWP calls. |
| */ |
| private ValueCache fCachedReftypes = new ValueCache(); |
| private ValueCache fCachedObjects = new ValueCache(); |
| |
| /** The following are the stored results of JDWP calls. */ |
| private String fVersionDescription = null; // Text information on the VM |
| // version. |
| private int fJdwpMajorVersion; |
| private int fJdwpMinorVersion; |
| private String fVMVersion; // Target VM JRE version, as in the java.version |
| // property. |
| private String fVMName; // Target VM name, as in the java.vm.name property. |
| private boolean fGotIDSizes = false; |
| private int fFieldIDSize; |
| private int fMethodIDSize; |
| private int fObjectIDSize; |
| private int fReferenceTypeIDSize; |
| private int fFrameIDSize; |
| |
| private boolean fGotCapabilities = false; |
| private boolean fCanWatchFieldModification; |
| private boolean fCanWatchFieldAccess; |
| private boolean fCanGetBytecodes; |
| private boolean fCanGetSyntheticAttribute; |
| private boolean fCanGetOwnedMonitorInfo; |
| private boolean fCanGetCurrentContendedMonitor; |
| private boolean fCanGetMonitorInfo; |
| private boolean fCanRedefineClasses; |
| private boolean fCanAddMethod; |
| private boolean fCanUnrestrictedlyRedefineClasses; |
| private boolean fCanPopFrames; |
| private boolean fCanUseInstanceFilters; |
| private boolean fCanGetSourceDebugExtension; |
| private boolean fCanRequestVMDeathEvent; |
| private boolean fCanSetDefaultStratum; |
| private boolean fCanGetInstanceInfo; |
| private boolean fCanGetConstantPool; |
| private boolean fCanUseSourceNameFilters; |
| private boolean fCanForceEarlyReturn; |
| private boolean fCanRequestMonitorEvents; |
| private boolean fCanGetMonitorFrameInfo; |
| private boolean[] fHcrCapabilities = null; |
| |
| /* |
| * singletons for primitive types |
| */ |
| private BooleanTypeImpl fBooleanType; |
| private ByteTypeImpl fByteType; |
| private CharTypeImpl fCharType; |
| private DoubleTypeImpl fDoubleType; |
| private FloatTypeImpl fFloatType; |
| private IntegerTypeImpl fIntegerType; |
| private LongTypeImpl fLongType; |
| private ShortTypeImpl fShortType; |
| |
| /** |
| * Disconnected flag |
| */ |
| private boolean fIsDisconnected = false; |
| |
| /** |
| * The name of the current default stratum. |
| */ |
| private String fDefaultStratum; |
| private PacketReceiveManager fPacketReceiveManager; |
| private PacketSendManager fPacketSendManager; |
| |
| /** |
| * Creates a new Virtual Machine. |
| */ |
| public VirtualMachineImpl(Connection connection) { |
| super("VirtualMachine"); //$NON-NLS-1$ |
| fEventReqMgr = new EventRequestManagerImpl(this); |
| fEventQueue = new EventQueueImpl(this); |
| fRequestTimeout = ((VirtualMachineManagerImpl) Bootstrap |
| .virtualMachineManager()).getGlobalRequestTimeout(); |
| |
| fPacketReceiveManager = new PacketReceiveManager(connection, this); |
| Thread receiveThread = new Thread(fPacketReceiveManager, |
| JDIMessages.VirtualMachineImpl_0); |
| receiveThread.setDaemon(true); |
| fPacketReceiveManager.setPartnerThread(receiveThread); |
| receiveThread.start(); |
| |
| fPacketSendManager = new PacketSendManager(connection); |
| Thread sendThread = new Thread(fPacketSendManager, |
| JDIMessages.VirtualMachineImpl_1); |
| sendThread.setDaemon(true); |
| fPacketReceiveManager.setPartnerThread(sendThread); |
| sendThread.start(); |
| } |
| |
| /** |
| * @return Returns size of JDWP ID. |
| */ |
| public final int fieldIDSize() { |
| return fFieldIDSize; |
| } |
| |
| /** |
| * @return Returns size of JDWP ID. |
| */ |
| public final int methodIDSize() { |
| return fMethodIDSize; |
| } |
| |
| /** |
| * @return Returns size of JDWP ID. |
| */ |
| public final int objectIDSize() { |
| return fObjectIDSize; |
| } |
| |
| /** |
| * @return Returns size of JDWP ID. |
| */ |
| public final int referenceTypeIDSize() { |
| return fReferenceTypeIDSize; |
| } |
| |
| /** |
| * @return Returns size of JDWP ID. |
| */ |
| public final int frameIDSize() { |
| return fFrameIDSize; |
| } |
| |
| /** |
| * @return Returns cached mirror object, or null if method is not in cache. |
| */ |
| public ReferenceTypeImpl getCachedMirror(JdwpReferenceTypeID ID) { |
| return (ReferenceTypeImpl) fCachedReftypes.get(ID); |
| } |
| |
| /** |
| * @return Returns cached mirror object, or null if method is not in cache. |
| */ |
| public ObjectReferenceImpl getCachedMirror(JdwpObjectID ID) { |
| return (ObjectReferenceImpl) fCachedObjects.get(ID); |
| } |
| |
| /** |
| * Adds mirror object to cache. |
| */ |
| public void addCachedMirror(ReferenceTypeImpl mirror) { |
| fCachedReftypes.put(mirror.getRefTypeID(), mirror); |
| // TBD: It is now yet possible to only ask for unload events for |
| // classes that we know of due to a limitation in the J9 VM. |
| // eventRequestManagerImpl().enableInternalClasUnloadEvent(mirror); |
| } |
| |
| /** |
| * Adds mirror object to cache. |
| */ |
| public void addCachedMirror(ObjectReferenceImpl mirror) { |
| fCachedObjects.put(mirror.getObjectID(), mirror); |
| } |
| |
| /** |
| * Flushes all stored Jdwp results. |
| */ |
| public void flushStoredJdwpResults() { |
| // All known classes also become invalid. |
| Iterator<Object> iter = fCachedReftypes.values().iterator(); |
| while (iter.hasNext()) { |
| ReferenceTypeImpl refType = (ReferenceTypeImpl) iter.next(); |
| refType.flushStoredJdwpResults(); |
| } |
| |
| fVersionDescription = null; |
| fGotIDSizes = false; |
| fHcrCapabilities = null; |
| } |
| |
| /* |
| * Removes a known class. A class/interface is known if we have ever |
| * received its ReferenceTypeID and we have not received an unload event for |
| * it. |
| */ |
| public final void removeKnownRefType(String signature) { |
| List<ReferenceType> refTypeList = classesBySignature(signature); |
| if (refTypeList.isEmpty()) |
| return; |
| |
| // If we have only one known class for this signature, we known that |
| // this is the class |
| // to be removed. |
| if (refTypeList.size() == 1) { |
| ReferenceTypeImpl refType = (ReferenceTypeImpl) refTypeList.get(0); |
| refType.flushStoredJdwpResults(); |
| fCachedReftypes.remove(refType.getRefTypeID()); |
| return; |
| } |
| |
| // We have more than one known class for the signature, let's find the |
| // unloaded one(s). |
| Iterator<ReferenceType> iter = refTypeList.iterator(); |
| while (iter.hasNext()) { |
| ReferenceTypeImpl refType = (ReferenceTypeImpl) iter.next(); |
| boolean prepared = false; |
| try { |
| prepared = refType.isPrepared(); |
| } catch (ObjectCollectedException exception) { |
| // The type is unloaded. Fall through |
| } |
| if (!prepared) { |
| refType.flushStoredJdwpResults(); |
| iter.remove(); |
| fCachedReftypes.remove(refType.getRefTypeID()); |
| } |
| } |
| } |
| |
| /* |
| * @exception Throws UnsupportedOperationException if VM does not support J9 |
| * HCR. |
| */ |
| public void checkHCRSupported() throws UnsupportedOperationException { |
| if (!isHCRSupported()) |
| throw new UnsupportedOperationException( |
| NLS.bind(JDIMessages.VirtualMachineImpl_Target_VM__0__does_not_support_Hot_Code_Replacement_1, new String[] { name() })); |
| } |
| |
| /* |
| * Returns whether J9 HCR is supported |
| */ |
| public boolean isHCRSupported() throws UnsupportedOperationException { |
| return name().equals("j9"); //$NON-NLS-1$ |
| } |
| |
| /* |
| * @return Returns Manager for receiving packets from the Virtual Machine. |
| */ |
| public final PacketReceiveManager packetReceiveManager() { |
| return fPacketReceiveManager; |
| } |
| |
| /* |
| * @return Returns Manager for sending packets to the Virtual Machine. |
| */ |
| public final PacketSendManager packetSendManager() { |
| /* |
| * Before we send out first bytes to the VM by JDI calls, we need some |
| * initial requests: - Get the sizes of the IDs (fieldID, method ID |
| * etc.) that the VM uses; - Request class prepare and unload events. We |
| * used these to cache classes/interfaces and map their signatures. |
| */ |
| if (!fGotIDSizes) { |
| getIDSizes(); |
| if (!fGotIDSizes) { // We can't do much without them. |
| disconnectVM(); |
| throw new VMDisconnectedException( |
| JDIMessages.VirtualMachineImpl_Failed_to_get_ID_sizes_2); |
| } |
| |
| // TBD: This call should be moved to addKnownRefType() when it can |
| // be made specific |
| // for a reference type. |
| eventRequestManagerImpl().enableInternalClasUnloadEvent(); |
| } |
| |
| return fPacketSendManager; |
| } |
| |
| /** |
| * Returns all loaded types (classes, interfaces, and array types). For each |
| * loaded type in the target VM a ReferenceType will be placed in the |
| * returned list. |
| */ |
| @Override |
| public List<ReferenceType> allClasses() { |
| // Note that this information should not be cached. |
| initJdwpRequest(); |
| try { |
| boolean withGenericSignature = virtualMachineImpl() |
| .isJdwpVersionGreaterOrEqual(1, 5); |
| int jdwpCommand = withGenericSignature ? JdwpCommandPacket.VM_ALL_CLASSES_WITH_GENERIC |
| : JdwpCommandPacket.VM_ALL_CLASSES; |
| JdwpReplyPacket replyPacket = requestVM(jdwpCommand); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$ |
| List<ReferenceType> elements = new ArrayList<>(nrOfElements); |
| for (int i = 0; i < nrOfElements; i++) { |
| ReferenceTypeImpl elt = ReferenceTypeImpl |
| .readWithTypeTagAndSignature(this, |
| withGenericSignature, replyData); |
| if (elt == null) { |
| continue; |
| } |
| readInt("status", ReferenceTypeImpl.classStatusStrings(), replyData); //$NON-NLS-1$ |
| elements.add(elt); |
| } |
| return elements; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| |
| } |
| |
| /** |
| * @return Returns an iterator over all loaded classes. |
| */ |
| protected final Iterator<ReferenceType> allRefTypes() { |
| return allClasses().iterator(); |
| } |
| |
| /** |
| * @return Returns an iterator over all cached classes. |
| */ |
| protected final Iterator<Object> allCachedRefTypes() { |
| return fCachedReftypes.values().iterator(); |
| } |
| |
| /** |
| * Returns a list of the currently running threads. For each running thread |
| * in the target VM, a ThreadReference that mirrors it is placed in the |
| * list. |
| */ |
| @Override |
| public List<ThreadReference> allThreads() { |
| // Note that this information should not be cached. |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.VM_ALL_THREADS); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$ |
| List<ThreadReference> elements = new ArrayList<>(nrOfElements); |
| for (int i = 0; i < nrOfElements; i++) { |
| ThreadReferenceImpl elt = ThreadReferenceImpl.read(this, |
| replyData); |
| if (elt == null) { |
| continue; |
| } |
| elements.add(elt); |
| } |
| return elements; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * Retrieve this VM's capabilities. |
| */ |
| public void getCapabilities() { |
| if (fGotCapabilities) |
| return; |
| |
| int command = JdwpCommandPacket.VM_CAPABILITIES; |
| if (isJdwpVersionGreaterOrEqual(1, 4)) { |
| command = JdwpCommandPacket.VM_CAPABILITIES_NEW; |
| } |
| |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(command); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| |
| fCanWatchFieldModification = readBoolean( |
| "watch field modification", replyData); //$NON-NLS-1$ |
| fCanWatchFieldAccess = readBoolean("watch field access", replyData); //$NON-NLS-1$ |
| fCanGetBytecodes = readBoolean("get bytecodes", replyData); //$NON-NLS-1$ |
| fCanGetSyntheticAttribute = readBoolean("synth. attr", replyData); //$NON-NLS-1$ |
| fCanGetOwnedMonitorInfo = readBoolean( |
| "owned monitor info", replyData); //$NON-NLS-1$ |
| fCanGetCurrentContendedMonitor = readBoolean( |
| "curr. contended monitor", replyData); //$NON-NLS-1$ |
| fCanGetMonitorInfo = readBoolean("monitor info", replyData); //$NON-NLS-1$ |
| if (command == JdwpCommandPacket.VM_CAPABILITIES_NEW) { |
| // extended capabilities |
| fCanRedefineClasses = readBoolean("redefine classes", replyData); //$NON-NLS-1$ |
| fCanAddMethod = readBoolean("add method", replyData); //$NON-NLS-1$ |
| fCanUnrestrictedlyRedefineClasses = readBoolean( |
| "unrestrictedly redefine classes", replyData); //$NON-NLS-1$ |
| fCanPopFrames = readBoolean("pop frames", replyData); //$NON-NLS-1$ |
| fCanUseInstanceFilters = readBoolean( |
| "use instance filters", replyData); //$NON-NLS-1$ |
| fCanGetSourceDebugExtension = readBoolean( |
| "get source debug extension", replyData); //$NON-NLS-1$ |
| fCanRequestVMDeathEvent = readBoolean( |
| "request vm death", replyData); //$NON-NLS-1$ |
| fCanSetDefaultStratum = readBoolean( |
| "set default stratum", replyData); //$NON-NLS-1$ |
| fCanGetInstanceInfo = readBoolean("instance info", replyData); //$NON-NLS-1$ |
| fCanRequestMonitorEvents = readBoolean( |
| "request monitor events", replyData); //$NON-NLS-1$ |
| fCanGetMonitorFrameInfo = readBoolean( |
| "monitor frame info", replyData); //$NON-NLS-1$ |
| fCanUseSourceNameFilters = readBoolean( |
| "source name filters", replyData); //$NON-NLS-1$ |
| fCanGetConstantPool = readBoolean("constant pool", replyData); //$NON-NLS-1$ |
| fCanForceEarlyReturn = readBoolean( |
| "force early return", replyData); //$NON-NLS-1$ |
| } else { |
| fCanRedefineClasses = false; |
| fCanAddMethod = false; |
| fCanUnrestrictedlyRedefineClasses = false; |
| fCanPopFrames = false; |
| fCanUseInstanceFilters = false; |
| fCanGetSourceDebugExtension = false; |
| fCanRequestVMDeathEvent = false; |
| fCanSetDefaultStratum = false; |
| fCanGetInstanceInfo = false; |
| fCanGetConstantPool = false; |
| fCanUseSourceNameFilters = false; |
| fCanForceEarlyReturn = false; |
| fCanRequestMonitorEvents = false; |
| fCanGetMonitorFrameInfo = false; |
| } |
| fGotCapabilities = true; |
| } catch (IOException e) { |
| fGotIDSizes = false; |
| defaultIOExceptionHandler(e); |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @see com.sun.jdi.VirtualMachine#canForceEarlyReturn() |
| * @since 3.3 |
| */ |
| @Override |
| public boolean canForceEarlyReturn() { |
| getCapabilities(); |
| return fCanForceEarlyReturn; |
| } |
| |
| /** |
| * @return Returns true if this implementation supports the retrieval of a |
| * method's bytecodes. |
| */ |
| @Override |
| public boolean canGetBytecodes() { |
| getCapabilities(); |
| return fCanGetBytecodes; |
| } |
| |
| /** |
| * @return Returns true if this implementation supports the retrieval of the |
| * monitor for which a thread is currently waiting. |
| */ |
| @Override |
| public boolean canGetCurrentContendedMonitor() { |
| getCapabilities(); |
| return fCanGetCurrentContendedMonitor; |
| } |
| |
| /** |
| * @see com.sun.jdi.VirtualMachine#canGetInstanceInfo() |
| * @since 3.3 |
| */ |
| @Override |
| public boolean canGetInstanceInfo() { |
| getCapabilities(); |
| return fCanGetInstanceInfo; |
| } |
| |
| /** |
| * @see com.sun.jdi.VirtualMachine#canGetMethodReturnValues() |
| * @since 3.3 |
| */ |
| @Override |
| public boolean canGetMethodReturnValues() { |
| return isJdwpVersionGreaterOrEqual(1, 6); |
| } |
| |
| /** |
| * @return Returns true if this implementation supports the retrieval of the |
| * monitor information for an object. |
| */ |
| @Override |
| public boolean canGetMonitorInfo() { |
| getCapabilities(); |
| return fCanGetMonitorInfo; |
| } |
| |
| /** |
| * @see com.sun.jdi.VirtualMachine#canGetMonitorFrameInfo() |
| * @since 3.3 |
| */ |
| @Override |
| public boolean canGetMonitorFrameInfo() { |
| getCapabilities(); |
| return fCanGetMonitorFrameInfo; |
| } |
| |
| /** |
| * @return Returns true if this implementation supports the retrieval of the |
| * monitors owned by a thread. |
| */ |
| @Override |
| public boolean canGetOwnedMonitorInfo() { |
| getCapabilities(); |
| return fCanGetOwnedMonitorInfo; |
| } |
| |
| /** |
| * @return Returns true if this implementation supports the query of the |
| * synthetic attribute of a method or field. |
| */ |
| @Override |
| public boolean canGetSyntheticAttribute() { |
| getCapabilities(); |
| return fCanGetSyntheticAttribute; |
| } |
| |
| /** |
| * @see com.sun.jdi.VirtualMachine#canRequestMonitorEvents() |
| * @since 3.3 |
| */ |
| @Override |
| public boolean canRequestMonitorEvents() { |
| getCapabilities(); |
| return fCanRequestMonitorEvents; |
| } |
| |
| /** |
| * @return Returns true if this implementation supports watchpoints for |
| * field access. |
| */ |
| @Override |
| public boolean canWatchFieldAccess() { |
| getCapabilities(); |
| return fCanWatchFieldAccess; |
| } |
| |
| /** |
| * @return Returns true if this implementation supports watchpoints for |
| * field modification. |
| */ |
| @Override |
| public boolean canWatchFieldModification() { |
| getCapabilities(); |
| return fCanWatchFieldModification; |
| } |
| |
| /** |
| * @return Returns the loaded reference types that match a given signature. |
| */ |
| public List<ReferenceType> classesBySignature(String signature) { |
| // Note that this information should not be cached. |
| initJdwpRequest(); |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| writeString(signature, "signature", outData); //$NON-NLS-1$ |
| |
| JdwpReplyPacket replyPacket = requestVM( |
| JdwpCommandPacket.VM_CLASSES_BY_SIGNATURE, outBytes); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$ |
| List<ReferenceType> elements = new ArrayList<>(nrOfElements); |
| for (int i = 0; i < nrOfElements; i++) { |
| ReferenceTypeImpl elt = ReferenceTypeImpl.readWithTypeTag(this, |
| replyData); |
| readInt("status", ReferenceTypeImpl.classStatusStrings(), replyData); //$NON-NLS-1$ |
| if (elt == null) { |
| continue; |
| } |
| elements.add(elt); |
| } |
| return elements; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#classesByName(java.lang.String) |
| */ |
| @Override |
| public List<ReferenceType> classesByName(String name) { |
| String signature = TypeImpl.classNameToSignature(name); |
| return classesBySignature(signature); |
| } |
| |
| /** |
| * Invalidates this virtual machine mirror. |
| */ |
| @Override |
| public void dispose() { |
| initJdwpRequest(); |
| try { |
| requestVM(JdwpCommandPacket.VM_DISPOSE); |
| disconnectVM(); |
| } catch (VMDisconnectedException e) { |
| // The VM can exit before we receive the reply. |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#eventQueue() |
| */ |
| @Override |
| public EventQueue eventQueue() { |
| return fEventQueue; |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#eventRequestManager() |
| */ |
| @Override |
| public EventRequestManager eventRequestManager() { |
| return fEventReqMgr; |
| } |
| |
| /** |
| * @return Returns EventRequestManagerImpl that creates all event objects on |
| * request. |
| */ |
| public EventRequestManagerImpl eventRequestManagerImpl() { |
| return fEventReqMgr; |
| } |
| |
| /** |
| * Causes the mirrored VM to terminate with the given error code. |
| */ |
| @Override |
| public void exit(int exitCode) { |
| initJdwpRequest(); |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| writeInt(exitCode, "exit code", outData); //$NON-NLS-1$ |
| requestVM(JdwpCommandPacket.VM_EXIT, outBytes); |
| disconnectVM(); |
| } catch (VMDisconnectedException e) { |
| // The VM can exit before we receive the reply. |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#mirrorOf(byte) |
| */ |
| @Override |
| public ByteValue mirrorOf(byte value) { |
| return new ByteValueImpl(virtualMachineImpl(), Byte.valueOf(value)); |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#mirrorOf(char) |
| */ |
| @Override |
| public CharValue mirrorOf(char value) { |
| return new CharValueImpl(virtualMachineImpl(), Character.valueOf(value)); |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#mirrorOf(double) |
| */ |
| @Override |
| public DoubleValue mirrorOf(double value) { |
| return new DoubleValueImpl(virtualMachineImpl(), Double.valueOf(value)); |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#mirrorOf(float) |
| */ |
| @Override |
| public FloatValue mirrorOf(float value) { |
| return new FloatValueImpl(virtualMachineImpl(), Float.valueOf(value)); |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#mirrorOf(int) |
| */ |
| @Override |
| public IntegerValue mirrorOf(int value) { |
| return new IntegerValueImpl(virtualMachineImpl(), Integer.valueOf(value)); |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#mirrorOf(long) |
| */ |
| @Override |
| public LongValue mirrorOf(long value) { |
| return new LongValueImpl(virtualMachineImpl(), Long.valueOf(value)); |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#mirrorOf(short) |
| */ |
| @Override |
| public ShortValue mirrorOf(short value) { |
| return new ShortValueImpl(virtualMachineImpl(), Short.valueOf(value)); |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#mirrorOf(boolean) |
| */ |
| @Override |
| public BooleanValue mirrorOf(boolean value) { |
| return new BooleanValueImpl(virtualMachineImpl(), |
| Boolean.valueOf(value)); |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#mirrorOf(java.lang.String) |
| */ |
| @Override |
| public StringReference mirrorOf(String value) { |
| initJdwpRequest(); |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| writeString(value, "string value", outData); //$NON-NLS-1$ |
| |
| JdwpReplyPacket replyPacket = requestVM( |
| JdwpCommandPacket.VM_CREATE_STRING, outBytes); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| |
| DataInputStream replyData = replyPacket.dataInStream(); |
| StringReference result = StringReferenceImpl.read(this, replyData); |
| return result; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#mirrorOfVoid() |
| */ |
| @Override |
| public VoidValue mirrorOfVoid() { |
| return new VoidValueImpl(this); |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#process() |
| */ |
| @Override |
| public Process process() { |
| return fLaunchedProcess; |
| } |
| |
| /** |
| * Sets Process object for this virtual machine if launched by a |
| * LaunchingConnector. |
| */ |
| public void setLaunchedProcess(Process proc) { |
| fLaunchedProcess = proc; |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#resume() |
| */ |
| @Override |
| public void resume() { |
| initJdwpRequest(); |
| try { |
| resetThreadEventFlags(); |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.VM_RESUME); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#setDebugTraceMode(int) |
| */ |
| @Override |
| public void setDebugTraceMode(int traceFlags) { |
| // We don't have trace info. |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#suspend() |
| */ |
| @Override |
| public void suspend() { |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.VM_SUSPEND); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#topLevelThreadGroups() |
| */ |
| @Override |
| public List<ThreadGroupReference> topLevelThreadGroups() { |
| // Note that this information should not be cached. |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.VM_TOP_LEVEL_THREAD_GROUPS); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| |
| DataInputStream replyData = replyPacket.dataInStream(); |
| int nrGroups = readInt("nr of groups", replyData); //$NON-NLS-1$ |
| ArrayList<ThreadGroupReference> result = new ArrayList<>(nrGroups); |
| for (int i = 0; i < nrGroups; i++) { |
| ThreadGroupReferenceImpl threadGroup = ThreadGroupReferenceImpl.read(this, replyData); |
| result.add(threadGroup); |
| } |
| return result; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#name() |
| */ |
| @Override |
| public String name() { |
| getVersionInfo(); |
| return fVMName; |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#version() |
| */ |
| @Override |
| public String version() { |
| getVersionInfo(); |
| return fVMVersion; |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#description() |
| */ |
| @Override |
| public String description() { |
| getVersionInfo(); |
| return fVersionDescription; |
| } |
| |
| /** |
| * Reset event flags of all threads. |
| */ |
| private void resetThreadEventFlags() { |
| Iterator<ThreadReference> iter = allThreads().iterator(); |
| ThreadReferenceImpl thread; |
| while (iter.hasNext()) { |
| thread = (ThreadReferenceImpl) iter.next(); |
| thread.resetEventFlags(); |
| } |
| } |
| |
| /** |
| * Request and fetch ID sizes of Virtual Machine. |
| */ |
| private void getIDSizes() { |
| if (fGotIDSizes) |
| return; |
| |
| /* |
| * fGotIDSizes must first be assigned true to prevent an infinite loop |
| * because getIDSizes() calls requestVM which calls packetSendManager. |
| */ |
| fGotIDSizes = true; |
| |
| // We use a different mirror to avoid having verbose output mixed with |
| // the initiating command. |
| MirrorImpl mirror = new VoidValueImpl(this); |
| |
| mirror.initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = mirror |
| .requestVM(JdwpCommandPacket.VM_ID_SIZES); |
| mirror.defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| |
| fFieldIDSize = mirror.readInt("field ID size", replyData); //$NON-NLS-1$ |
| fMethodIDSize = mirror.readInt("method ID size", replyData); //$NON-NLS-1$ |
| fObjectIDSize = mirror.readInt("object ID size", replyData); //$NON-NLS-1$ |
| fReferenceTypeIDSize = mirror.readInt("refType ID size", replyData); //$NON-NLS-1$ |
| fFrameIDSize = mirror.readInt("frame ID size", replyData); //$NON-NLS-1$ |
| } catch (IOException e) { |
| fGotIDSizes = false; |
| mirror.defaultIOExceptionHandler(e); |
| } finally { |
| mirror.handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * Retrieves version info of the VM. |
| */ |
| public void getVersionInfo() { |
| if (fVersionDescription != null) |
| return; |
| |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.VM_VERSION); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| |
| fVersionDescription = readString("version descr.", replyData); //$NON-NLS-1$ |
| fJdwpMajorVersion = readInt("major version", replyData); //$NON-NLS-1$ |
| fJdwpMinorVersion = readInt("minor version", replyData); //$NON-NLS-1$ |
| fVMVersion = readString("version", replyData); //$NON-NLS-1$ |
| fVMName = readString("name", replyData); //$NON-NLS-1$ |
| |
| if ((fVMName != null) && fVMName.equals("KVM")) { //$NON-NLS-1$ |
| // KVM requires class preparation events in order |
| // to resolve things correctly |
| eventRequestManagerImpl().enableInternalClassPrepareEvent(); |
| } |
| |
| } catch (IOException e) { |
| fVersionDescription = null; |
| defaultIOExceptionHandler(e); |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * Retrieves the HCR capabilities of the VM. |
| */ |
| public void getHCRCapabilities() { |
| if (fHcrCapabilities != null) |
| return; |
| fHcrCapabilities = new boolean[HCR_CAN_REENTER_ON_EXIT + 1]; |
| |
| if (isHCRSupported()) { |
| initJdwpRequest(); |
| try { |
| JdwpReplyPacket replyPacket = requestVM(JdwpCommandPacket.HCR_CAPABILITIES); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| |
| fHcrCapabilities[HCR_CAN_RELOAD_CLASSES] = readBoolean( |
| "reload classes", replyData); //$NON-NLS-1$ |
| fHcrCapabilities[HCR_CAN_GET_CLASS_VERSION] = readBoolean( |
| "get class version", replyData); //$NON-NLS-1$ |
| fHcrCapabilities[HCR_CAN_DO_RETURN] = readBoolean( |
| "do return", replyData); //$NON-NLS-1$ |
| fHcrCapabilities[HCR_CAN_REENTER_ON_EXIT] = readBoolean( |
| "reenter on exit", replyData); //$NON-NLS-1$ |
| } catch (IOException e) { |
| fHcrCapabilities = null; |
| defaultIOExceptionHandler(e); |
| } finally { |
| handledJdwpRequest(); |
| } |
| } else { |
| for (int i = 0; i < fHcrCapabilities.length; i++) { |
| fHcrCapabilities[i] = false; |
| } |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdi.hcr.VirtualMachine#canReloadClasses() |
| */ |
| @Override |
| public boolean canReloadClasses() { |
| getHCRCapabilities(); |
| return fHcrCapabilities[HCR_CAN_RELOAD_CLASSES]; |
| } |
| |
| /** |
| * @return Returns Whether VM can get the version of a given class file. |
| */ |
| public boolean canGetClassFileVersion1() { |
| getHCRCapabilities(); |
| return fHcrCapabilities[HCR_CAN_GET_CLASS_VERSION]; |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#canGetClassFileVersion() |
| */ |
| @Override |
| public boolean canGetClassFileVersion() { |
| return isJdwpVersionGreaterOrEqual(1, 6); |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#canGetConstantPool() |
| */ |
| @Override |
| public boolean canGetConstantPool() { |
| getCapabilities(); |
| return fCanGetConstantPool; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdi.hcr.VirtualMachine#canDoReturn() |
| */ |
| @Override |
| public boolean canDoReturn() { |
| getHCRCapabilities(); |
| return fHcrCapabilities[HCR_CAN_DO_RETURN]; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdi.hcr.VirtualMachine#canReenterOnExit() |
| */ |
| @Override |
| public boolean canReenterOnExit() { |
| getHCRCapabilities(); |
| return fHcrCapabilities[HCR_CAN_REENTER_ON_EXIT]; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdi.hcr.VirtualMachine#classesHaveChanged(java.lang.String[]) |
| */ |
| @Override |
| public int classesHaveChanged(String[] names) { |
| checkHCRSupported(); |
| // We convert the class/interface names to signatures. |
| String[] signatures = new String[names.length]; |
| |
| initJdwpRequest(); |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| writeInt(names.length, "length", outData); //$NON-NLS-1$ |
| for (int i = 0; i < names.length; i++) { |
| signatures[i] = TypeImpl.classNameToSignature(names[i]); |
| writeString(signatures[i], "signature", outData); //$NON-NLS-1$ |
| } |
| |
| JdwpReplyPacket replyPacket = requestVM( |
| JdwpCommandPacket.HCR_CLASSES_HAVE_CHANGED, outBytes); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| DataInputStream replyData = replyPacket.dataInStream(); |
| |
| byte resultFlag = readByte("result", resultHCRMap(), replyData); //$NON-NLS-1$ |
| switch (resultFlag) { |
| case HCR_RELOAD_SUCCESS: |
| return RELOAD_SUCCESS; |
| case HCR_RELOAD_FAILURE: |
| return RELOAD_FAILURE; |
| case HCR_RELOAD_IGNORED: |
| return RELOAD_IGNORED; |
| } |
| throw new InternalError( |
| JDIMessages.VirtualMachineImpl_Invalid_result_flag_in_Classes_Have_Changed_response___3 |
| + resultFlag + JDIMessages.VirtualMachineImpl__4); // |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return 0; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * @return Returns description of Mirror object. |
| */ |
| @Override |
| public String toString() { |
| try { |
| return name(); |
| } catch (Exception e) { |
| return fDescription; |
| } |
| } |
| |
| /** |
| * Retrieves constant mappings. |
| */ |
| public static void getConstantMaps() { |
| if (fgHCRResultMap != null) { |
| return; |
| } |
| |
| Field[] fields = VirtualMachineImpl.class.getDeclaredFields(); |
| fgHCRResultMap = new HashMap<>(); |
| for (Field field : fields) { |
| if ((field.getModifiers() & Modifier.PUBLIC) == 0 |
| || (field.getModifiers() & Modifier.STATIC) == 0 |
| || (field.getModifiers() & Modifier.FINAL) == 0) { |
| continue; |
| } |
| |
| try { |
| String name = field.getName(); |
| if (name.startsWith("HCR_RELOAD_")) { //$NON-NLS-1$ |
| Integer intValue = Integer.valueOf(field.getInt(null)); |
| name = name.substring(4); |
| fgHCRResultMap.put(intValue, name); |
| } |
| } catch (IllegalAccessException e) { |
| // Will not occur for own class. |
| } catch (IllegalArgumentException e) { |
| // Should not occur. |
| // We should take care that all public static final constants |
| // in this class are numbers that are convertible to int. |
| } |
| } |
| } |
| |
| /** |
| * @return Returns a map with string representations of tags. |
| */ |
| public static Map<Integer, String> resultHCRMap() { |
| getConstantMaps(); |
| return fgHCRResultMap; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdi.VirtualMachine#setRequestTimeout(int) |
| */ |
| @Override |
| public void setRequestTimeout(int timeout) { |
| fRequestTimeout = timeout; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jdi.VirtualMachine#getRequestTimeout() |
| */ |
| @Override |
| public int getRequestTimeout() { |
| return fRequestTimeout; |
| } |
| |
| /** |
| * Returns whether the JDWP version is greater than or equal to the |
| * specified major/minor version numbers. |
| * |
| * @return whether the JDWP version is greater than or equal to the |
| * specified major/minor version numbers |
| */ |
| public boolean isJdwpVersionGreaterOrEqual(int major, int minor) { |
| getVersionInfo(); |
| return (fJdwpMajorVersion > major) |
| || (fJdwpMajorVersion == major && fJdwpMinorVersion >= minor); |
| } |
| |
| @Override |
| public void redefineClasses(Map<? extends ReferenceType, byte[]> typesToBytes) { |
| if (!canRedefineClasses()) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| initJdwpRequest(); |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| writeInt(typesToBytes.size(), "classes", outData); //$NON-NLS-1$ |
| |
| Set<? extends ReferenceType> types = typesToBytes.keySet(); |
| Iterator<? extends ReferenceType> iter = types.iterator(); |
| while (iter.hasNext()) { |
| ReferenceTypeImpl type = (ReferenceTypeImpl) iter.next(); |
| type.write(this, outData); |
| byte[] bytes = typesToBytes.get(type); |
| writeInt(bytes.length, "classfile", outData); //$NON-NLS-1$ |
| for (byte b : bytes) { |
| writeByte(b, "classByte", outData); //$NON-NLS-1$ |
| } |
| fCachedReftypes.remove(type.getRefTypeID()); // flush local |
| // cache of |
| // redefined |
| // types |
| } |
| |
| JdwpReplyPacket reply = requestVM( |
| JdwpCommandPacket.VM_REDEFINE_CLASSES, outBytes); |
| switch (reply.errorCode()) { |
| case JdwpReplyPacket.UNSUPPORTED_VERSION: |
| throw new UnsupportedClassVersionError(); |
| case JdwpReplyPacket.INVALID_CLASS_FORMAT: |
| throw new ClassFormatError(); |
| case JdwpReplyPacket.CIRCULAR_CLASS_DEFINITION: |
| throw new ClassCircularityError(); |
| case JdwpReplyPacket.FAILS_VERIFICATION: |
| throw new VerifyError(); |
| case JdwpReplyPacket.NAMES_DONT_MATCH: |
| throw new NoClassDefFoundError(); |
| case JdwpReplyPacket.ADD_METHOD_NOT_IMPLEMENTED: |
| throw new UnsupportedOperationException( |
| JDIMessages.VirtualMachineImpl_Add_method_not_implemented_1); |
| case JdwpReplyPacket.SCHEMA_CHANGE_NOT_IMPLEMENTED: |
| throw new UnsupportedOperationException( |
| JDIMessages.VirtualMachineImpl_Scheme_change_not_implemented_2); |
| case JdwpReplyPacket.HIERARCHY_CHANGE_NOT_IMPLEMENTED: |
| throw new UnsupportedOperationException( |
| JDIMessages.VirtualMachineImpl_Hierarchy_change_not_implemented_3); |
| case JdwpReplyPacket.DELETE_METHOD_NOT_IMPLEMENTED: |
| throw new UnsupportedOperationException( |
| JDIMessages.VirtualMachineImpl_Delete_method_not_implemented_4); |
| case JdwpReplyPacket.CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED: |
| throw new UnsupportedOperationException( |
| JDIMessages.VirtualMachineImpl_Class_modifiers_change_not_implemented_5); |
| case JdwpReplyPacket.METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED: |
| throw new UnsupportedOperationException( |
| JDIMessages.VirtualMachineImpl_Method_modifiers_change_not_implemented_6); |
| default: |
| defaultReplyErrorHandler(reply.errorCode()); |
| } |
| } catch (IOException ioe) { |
| defaultIOExceptionHandler(ioe); |
| return; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /* |
| * @see VirtualMachine#canRedefineClasses() |
| */ |
| @Override |
| public boolean canRedefineClasses() { |
| getCapabilities(); |
| return fCanRedefineClasses; |
| } |
| |
| /* |
| * @see VirtualMachine#canUseInstanceFilters() |
| */ |
| @Override |
| public boolean canUseInstanceFilters() { |
| getCapabilities(); |
| return fCanUseInstanceFilters; |
| } |
| |
| /* |
| * @see VirtualMachine#canAddMethod() |
| */ |
| @Override |
| public boolean canAddMethod() { |
| getCapabilities(); |
| return fCanAddMethod; |
| } |
| |
| /* |
| * @see VirtualMachine#canUnrestrictedlyRedefineClasses() |
| */ |
| @Override |
| public boolean canUnrestrictedlyRedefineClasses() { |
| getCapabilities(); |
| return fCanUnrestrictedlyRedefineClasses; |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#canUseSourceNameFilters() |
| */ |
| @Override |
| public boolean canUseSourceNameFilters() { |
| getCapabilities(); |
| return fCanUseSourceNameFilters; |
| } |
| |
| /* |
| * @see VirtualMachine#canPopFrames() |
| */ |
| @Override |
| public boolean canPopFrames() { |
| getCapabilities(); |
| return fCanPopFrames; |
| } |
| |
| /* |
| * @see VirtualMachine#canGetSourceDebugExtension() |
| */ |
| @Override |
| public boolean canGetSourceDebugExtension() { |
| getCapabilities(); |
| return fCanGetSourceDebugExtension; |
| } |
| |
| /* |
| * @see VirtualMachine#canRequestVMDeathEvent() |
| */ |
| @Override |
| public boolean canRequestVMDeathEvent() { |
| getCapabilities(); |
| return fCanRequestVMDeathEvent; |
| } |
| |
| public boolean canSetDefaultStratum() { |
| getCapabilities(); |
| return fCanSetDefaultStratum; |
| } |
| |
| /* |
| * @see VirtualMachine#setDefaultStratum(String) |
| */ |
| @Override |
| public void setDefaultStratum(String stratum) { |
| fDefaultStratum = stratum; |
| |
| if (!canSetDefaultStratum()) { |
| // TODO: how to inform the user that the VM doesn't manage |
| // setDefaultStartum ? |
| return; |
| } |
| if (stratum == null) { |
| stratum = ""; //$NON-NLS-1$ |
| } |
| initJdwpRequest(); |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| writeString(stratum, "stratum ID", outData); //$NON-NLS-1$ |
| |
| JdwpReplyPacket replyPacket = requestVM( |
| JdwpCommandPacket.VM_SET_DEFAULT_STRATUM, outBytes); |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#getDefaultStratum() |
| */ |
| @Override |
| public String getDefaultStratum() { |
| return fDefaultStratum; |
| } |
| |
| /* (non-Javadoc) |
| * @see com.sun.jdi.VirtualMachine#instanceCounts(java.util.List) |
| */ |
| @Override |
| public long[] instanceCounts(List<? extends ReferenceType> refTypes) { |
| if (refTypes == null) { |
| throw new NullPointerException(JDIMessages.VirtualMachineImpl_2); |
| } |
| int size = refTypes.size(); |
| if (size == 0) { |
| if (isJdwpVersionGreaterOrEqual(1, 6)) { |
| return new long[0]; |
| } |
| throw new UnsupportedOperationException(JDIMessages.ReferenceTypeImpl_27); |
| } |
| try { |
| ByteArrayOutputStream outBytes = new ByteArrayOutputStream(); |
| DataOutputStream outData = new DataOutputStream(outBytes); |
| writeInt(size, "size", outData); //$NON-NLS-1$ |
| for (int i = 0; i < size; i++) { |
| ((ReferenceTypeImpl) refTypes.get(i)).getRefTypeID().write( |
| outData); |
| } |
| JdwpReplyPacket replyPacket = requestVM( |
| JdwpCommandPacket.VM_INSTANCE_COUNTS, outBytes); |
| switch (replyPacket.errorCode()) { |
| case JdwpReplyPacket.INVALID_CLASS: |
| case JdwpReplyPacket.INVALID_OBJECT: |
| throw new ObjectCollectedException( |
| JDIMessages.class_or_object_not_known); |
| case JdwpReplyPacket.ILLEGAL_ARGUMENT: |
| throw new IllegalArgumentException( |
| JDIMessages.VirtualMachineImpl_count_less_than_zero); |
| case JdwpReplyPacket.NOT_IMPLEMENTED: |
| throw new UnsupportedOperationException( |
| JDIMessages.ReferenceTypeImpl_27); |
| case JdwpReplyPacket.VM_DEAD: |
| throw new VMDisconnectedException(JDIMessages.vm_dead); |
| } |
| defaultReplyErrorHandler(replyPacket.errorCode()); |
| |
| DataInputStream replyData = replyPacket.dataInStream(); |
| int counts = readInt("counts", replyData); //$NON-NLS-1$ |
| if (counts != size) { |
| throw new InternalError(JDIMessages.VirtualMachineImpl_3); |
| } |
| long[] ret = new long[counts]; |
| for (int i = 0; i < counts; i++) { |
| ret[i] = readLong("ref count", replyData); //$NON-NLS-1$ |
| } |
| return ret; |
| } catch (IOException e) { |
| defaultIOExceptionHandler(e); |
| return null; |
| } finally { |
| handledJdwpRequest(); |
| } |
| } |
| |
| /** |
| * Returns whether this VM is disconnected. |
| * |
| * @return whether this VM is disconnected |
| */ |
| public boolean isDisconnected() { |
| return fIsDisconnected; |
| } |
| |
| /** |
| * Sets whether this VM is disconnected. |
| * |
| * @param disconected |
| * whether this VM is disconnected |
| */ |
| public synchronized void setDisconnected(boolean disconnected) { |
| fIsDisconnected = disconnected; |
| } |
| |
| /** |
| * Return the boolean type for this VM. |
| */ |
| protected BooleanTypeImpl getBooleanType() { |
| if (fBooleanType == null) { |
| fBooleanType = new BooleanTypeImpl(this); |
| } |
| return fBooleanType; |
| } |
| |
| /** |
| * Return the byte type for this VM. |
| */ |
| protected ByteTypeImpl getByteType() { |
| if (fByteType == null) { |
| fByteType = new ByteTypeImpl(this); |
| } |
| return fByteType; |
| } |
| |
| /** |
| * Return the char type for this VM. |
| */ |
| protected CharTypeImpl getCharType() { |
| if (fCharType == null) { |
| fCharType = new CharTypeImpl(this); |
| } |
| return fCharType; |
| } |
| |
| /** |
| * Return the double type for this VM. |
| */ |
| protected DoubleTypeImpl getDoubleType() { |
| if (fDoubleType == null) { |
| fDoubleType = new DoubleTypeImpl(this); |
| } |
| return fDoubleType; |
| } |
| |
| /** |
| * Return the float type for this VM. |
| */ |
| protected FloatTypeImpl getFloatType() { |
| if (fFloatType == null) { |
| fFloatType = new FloatTypeImpl(this); |
| } |
| return fFloatType; |
| } |
| |
| /** |
| * Return the integer type for this VM. |
| */ |
| protected IntegerTypeImpl getIntegerType() { |
| if (fIntegerType == null) { |
| fIntegerType = new IntegerTypeImpl(this); |
| } |
| return fIntegerType; |
| } |
| |
| /** |
| * Return the long type for this VM. |
| */ |
| protected LongTypeImpl getLongType() { |
| if (fLongType == null) { |
| fLongType = new LongTypeImpl(this); |
| } |
| return fLongType; |
| } |
| |
| /** |
| * Return the short type for this VM. |
| */ |
| protected ShortTypeImpl getShortType() { |
| if (fShortType == null) { |
| fShortType = new ShortTypeImpl(this); |
| } |
| return fShortType; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see com.sun.jdi.VirtualMachine#canBeModified() |
| */ |
| @Override |
| public boolean canBeModified() { |
| return true; |
| } |
| } |