/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * 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;
	}
}
