/*******************************************************************************
 * 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(), new Byte(value));
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.VirtualMachine#mirrorOf(char)
	 */
	@Override
	public CharValue mirrorOf(char value) {
		return new CharValueImpl(virtualMachineImpl(), new Character(value));
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.VirtualMachine#mirrorOf(double)
	 */
	@Override
	public DoubleValue mirrorOf(double value) {
		return new DoubleValueImpl(virtualMachineImpl(), new Double(value));
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.VirtualMachine#mirrorOf(float)
	 */
	@Override
	public FloatValue mirrorOf(float value) {
		return new FloatValueImpl(virtualMachineImpl(), new Float(value));
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.VirtualMachine#mirrorOf(int)
	 */
	@Override
	public IntegerValue mirrorOf(int value) {
		return new IntegerValueImpl(virtualMachineImpl(), new Integer(value));
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.VirtualMachine#mirrorOf(long)
	 */
	@Override
	public LongValue mirrorOf(long value) {
		return new LongValueImpl(virtualMachineImpl(), new Long(value));
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.VirtualMachine#mirrorOf(short)
	 */
	@Override
	public ShortValue mirrorOf(short value) {
		return new ShortValueImpl(virtualMachineImpl(), new Short(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 = new Integer(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;
	}
}
