/*******************************************************************************
 * 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
 *     Yavor Boyadzhiev <yavor.vasilev.boyadzhiev@sap.com> - Bug 162399
 *     Jesper Steen Møller <jesper@selskabet.org> - Bug 430839
 *******************************************************************************/
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.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket;
import org.eclipse.jdi.internal.jdwp.JdwpFieldID;
import org.eclipse.jdi.internal.jdwp.JdwpID;
import org.eclipse.jdi.internal.jdwp.JdwpMethodID;
import org.eclipse.jdi.internal.jdwp.JdwpReferenceTypeID;
import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket;
import org.eclipse.osgi.util.NLS;

import com.sun.jdi.AbsentInformationException;
import com.sun.jdi.ClassLoaderReference;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.ClassNotPreparedException;
import com.sun.jdi.ClassObjectReference;
import com.sun.jdi.ClassType;
import com.sun.jdi.Field;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.InterfaceType;
import com.sun.jdi.InternalException;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.InvocationException;
import com.sun.jdi.Location;
import com.sun.jdi.Method;
import com.sun.jdi.NativeMethodException;
import com.sun.jdi.ObjectCollectedException;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.Value;

/**
 * this class implements the corresponding interfaces declared by the JDI
 * specification. See the com.sun.jdi package for more information.
 *
 */
public abstract class ReferenceTypeImpl extends TypeImpl implements
		ReferenceType, org.eclipse.jdi.hcr.ReferenceType {

	/** ClassStatus Constants. */
	public static final int JDWP_CLASS_STATUS_VERIFIED = 1;
	public static final int JDWP_CLASS_STATUS_PREPARED = 2;
	public static final int JDWP_CLASS_STATUS_INITIALIZED = 4;
	public static final int JDWP_CLASS_STATUS_ERROR = 8;

	/** Mapping of command codes to strings. */
	private static String[] fgClassStatusStrings = null;

	/**
	 * Represent the data about one file info contained in one stratum in the
	 * SMAP.
	 */
	protected static class FileInfo {

		/**
		 * The id.
		 */
		protected int fFileId;

		/**
		 * The name of the source file.
		 */
		protected String fFileName;

		/**
		 * The path of the source file.
		 */
		protected String fAbsoluteFileName;

		/**
		 * Map line number in the input source file -> list of [start line in
		 * the output source file, range in the output source file]. (Integer ->
		 * List of int[2]).
		 */
		private HashMap<Integer, List<int[]>> fLineInfo;

		/**
		 * FileInfo constructor.
		 *
		 * @param fileId
		 *            the id.
		 * @param fileName
		 *            the name of the source file.
		 * @param absoluteFileName
		 *            the path of the source file (can be <code>null</code>).
		 */
		public FileInfo(int fileId, String fileName, String absoluteFileName) {
			fFileId = fileId;
			fFileName = fileName;
			fAbsoluteFileName = absoluteFileName;
			fLineInfo = new HashMap<>();
		}

		/**
		 * Add information about the mapping of one line. Associate a line in
		 * the input source file to a snippet of code in the output source file.
		 *
		 * @param inputLine
		 *            the line number in the input source file.
		 * @param outputStartLine
		 *            the number of the first line of the corresponding snippet
		 *            in the output source file.
		 * @param outputLineRange
		 *            the size of the corresponding snippet in the output source
		 *            file.
		 */
		public void addLineInfo(int inputLine, int outputStartLine,
				int outputLineRange) {
			Integer key = new Integer(inputLine);
			List<int[]> outputLines = fLineInfo.get(key);
			if (outputLines == null) {
				outputLines = new ArrayList<>();
				fLineInfo.put(key, outputLines);
			}
			outputLines.add(new int[] { outputStartLine, outputLineRange });
		}

		/**
		 * Return a list of line information about the code in the output source
		 * file associated to the given line in the input source file.
		 *
		 * @param lineNumber
		 *            the line number in the input source file.
		 * @return a List of int[2].
		 */
		public List<Integer> getOutputLinesForLine(int lineNumber) {
			List<Integer> list = new ArrayList<>();
			List<int[]> outputLines = fLineInfo.get(new Integer(lineNumber));
			if (outputLines != null) {
				for (Iterator<int[]> iter = outputLines.iterator(); iter.hasNext();) {
					int[] info = iter.next();
					int outputLineNumber = info[0];
					int length = info[1];
					if (length == 0) {
						length = length + 1;
					}
					for (int i = 0; i < length; i++) {
						list.add(new Integer(outputLineNumber++));
					}
				}
			}
			return list;
		}

		/**
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		@Override
		public boolean equals(Object object) {
			if (!(object instanceof FileInfo)) {
				return false;
			}
			return fFileId == ((FileInfo) object).fFileId;
		}

	}

	/**
	 * Represent the information contained in the SMAP about one stratum.
	 */
	protected static class Stratum {

		/**
		 * The id of this stratum.
		 */
		private String fId;

		/**
		 * The file info data associated to this stratum.
		 */
		private List<FileInfo> fFileInfos;

		/**
		 * Id of the primary file for this stratum.
		 */
		private int fPrimaryFileId;

		/**
		 * Map line number in the output source file -> list of line numbers in
		 * the input source file. (Integer -> List of Integer)
		 */
		private HashMap<Integer, List<int[]>> fOutputLineToInputLine;

		/**
		 * Stratum constructor.
		 *
		 * @param id
		 *            The id of this stratum.
		 */
		public Stratum(String id) {
			fId = id;
			fFileInfos = new ArrayList<>();
			fOutputLineToInputLine = new HashMap<>();
			fPrimaryFileId = -1;
		}

		/**
		 * Add a file info to this stratum.
		 *
		 * @param fileId
		 *            the id.
		 * @param fileName
		 *            the name of the source file.
		 */
		public void addFileInfo(int fileId, String fileName)
				throws AbsentInformationException {
			addFileInfo(fileId, fileName, null);
		}

		/**
		 * Add a file info to this stratum.
		 *
		 * @param fileId
		 *            the id.
		 * @param fileName
		 *            the name of the source file.
		 * @param absoluteFileName
		 *            the path of the source file.
		 */
		public void addFileInfo(int fileId, String fileName,
				String absoluteFileName) throws AbsentInformationException {
			if (fPrimaryFileId == -1) {
				fPrimaryFileId = fileId;
			}
			FileInfo fileInfo = new FileInfo(fileId, fileName, absoluteFileName);
			if (fFileInfos.contains(fileInfo)) {
				throw new AbsentInformationException(NLS.bind(
						JDIMessages.ReferenceTypeImpl_28, new String[] {
								Integer.toString(fileId), fId }));
			}
			fFileInfos.add(fileInfo);
		}

		/**
		 * Add line mapping information.
		 *
		 * @param inputStartLine
		 *            number of the first line in the input source file.
		 * @param lineFileId
		 *            id of the input source file.
		 * @param repeatCount
		 *            number of iterations.
		 * @param outputStartLine
		 *            number of the first line in the output source file.
		 * @param outputLineIncrement
		 *            number of line to increment at each iteration.
		 * @throws AbsentInformationException
		 */
		public void addLineInfo(int inputStartLine, int lineFileId,
				int repeatCount, int outputStartLine, int outputLineIncrement)
				throws AbsentInformationException {
			FileInfo fileInfo = null;
			// get the FileInfo object
			for (Iterator<FileInfo> iter = fFileInfos.iterator(); iter.hasNext();) {
				FileInfo element = iter.next();
				if (element.fFileId == lineFileId) {
					fileInfo = element;
				}
			}
			if (fileInfo == null) {
				throw new AbsentInformationException(NLS.bind(
						JDIMessages.ReferenceTypeImpl_29,
						new String[] { Integer.toString(lineFileId) }));
			}
			// add the data to the different hash maps.
			for (int i = 0; i < repeatCount; i++, inputStartLine++) {
				fileInfo.addLineInfo(inputStartLine, outputStartLine,
						outputLineIncrement);
				if (outputLineIncrement == 0) {
					// see bug 40022
					addLineInfoToMap(inputStartLine, lineFileId,
							outputStartLine);
				} else {
					for (int j = 0; j < outputLineIncrement; j++, outputStartLine++) {
						addLineInfoToMap(inputStartLine, lineFileId,
								outputStartLine);
					}
				}
			}
		}

		/**
		 * Add the data to the map.
		 */
		private void addLineInfoToMap(int inputStartLine, int lineFileId,
				int outputStartLine) {
			Integer key = new Integer(outputStartLine);
			List<int[]> inputLines = fOutputLineToInputLine.get(key);
			if (inputLines == null) {
				inputLines = new ArrayList<>();
				fOutputLineToInputLine.put(key, inputLines);
			}
			inputLines.add(new int[] { lineFileId, inputStartLine });
		}

		/**
		 * Return the FileInfo object for the specified source name. Return
		 * <code>null</code> if the specified name is the source name of no file
		 * info.
		 *
		 * @param sourceName
		 *            the source name to search.
		 */
		public FileInfo getFileInfo(String sourceName) {
			for (Iterator<FileInfo> iter = fFileInfos.iterator(); iter.hasNext();) {
				FileInfo fileInfo = iter.next();
				if (fileInfo.fFileName.equals(sourceName)) {
					return fileInfo;
				}
			}
			return null;
		}

		/**
		 * @param outputLineNumber
		 * @return
		 */
		public List<int[]> getInputLineInfos(int outputLineNumber) {
			return fOutputLineToInputLine.get(new Integer(
					outputLineNumber));
		}

	}

	/** ReferenceTypeID that corresponds to this reference. */
	private JdwpReferenceTypeID fReferenceTypeID;

	/** The following are the stored results of JDWP calls. */
	protected List<InterfaceType> fInterfaces = null;
	private List<Method> fMethods = null;
	private Hashtable<JdwpMethodID, Method> fMethodTable = null;
	private List<Field> fFields = null;
	private List<Method> fAllMethods = null;
	private List<Method> fVisibleMethods = null;
	private List<Field> fAllFields = null;
	private List<Field> fVisibleFields = null;
	private List<InterfaceType> fAllInterfaces = null;
	private Map<String, Map<String, List<Location>>> fStratumAllLineLocations = null;
	private String fSourceName = null;
	private int fModifierBits = -1;
	private ClassLoaderReferenceImpl fClassLoader = null;
	private ClassObjectReferenceImpl fClassObject = null;

	private String fGenericSignature; // 1.5 addition
	private boolean fGenericSignatureKnown; // 1.5 addition

	private boolean fGotClassFileVersion = false; // HCR addition.
	private int fClassFileVersion; // HCR addition.
	private boolean fIsHCREligible; // HCR addition.
	private boolean fIsVersionKnown; // HCR addition.

	private boolean fSourceDebugExtensionAvailable = true; // JSR-045 addition

	/**
	 * The default stratum id.
	 */
	private String fDefaultStratumId; // JSR-045 addition

	/**
	 * A map of the defined strata. Map stratum id -> Stratum object. (String ->
	 * Stratum).
	 */
	private Map<String, Stratum> fStrata; // JSR-045 addition

	/**
	 * The source map string returned by the VM.
	 */
	private String fSmap; // JSR-045 addition

	/**
	 * Creates new instance.
	 */
	protected ReferenceTypeImpl(String description, VirtualMachineImpl vmImpl,
			JdwpReferenceTypeID referenceTypeID) {
		super(description, vmImpl);
		fReferenceTypeID = referenceTypeID;
	}

	/**
	 * Creates new instance.
	 */
	protected ReferenceTypeImpl(String description, VirtualMachineImpl vmImpl,
			JdwpReferenceTypeID referenceTypeID, String signature,
			String genericSignature) {
		super(description, vmImpl);
		fReferenceTypeID = referenceTypeID;
		setSignature(signature);
		setGenericSignature(genericSignature);
	}

	/**
	 * @return Returns type tag.
	 */
	public abstract byte typeTag();

	/**
	 * Flushes all stored Jdwp results.
	 */
	public void flushStoredJdwpResults() {
		// Flush Methods.
		if (fMethods != null) {
			for (Method method : fMethods) {
				((MethodImpl)method).flushStoredJdwpResults();
			}
			fMethods = null;
			fMethodTable = null;
		}

		// Flush Fields.
		if (fFields != null) {
			for (Field field : fFields) {
				((FieldImpl)field).flushStoredJdwpResults();
			}
			fFields = null;
		}

		fInterfaces = null;
		fAllMethods = null;
		fVisibleMethods = null;
		fAllFields = null;
		fVisibleFields = null;
		fAllInterfaces = null;
		fStratumAllLineLocations = null;
		fSourceName = null;
		fModifierBits = -1;
		fClassLoader = null;
		fClassObject = null;
		fGotClassFileVersion = false;
		// java 1.5
		fGenericSignature = null;
		fGenericSignatureKnown = false;

		// JSR-045
		fSourceDebugExtensionAvailable = true;
		fDefaultStratumId = null;
		fStrata = null;
		fSmap = null;

		// The following cached results are stored higher up in the class
		// hierarchy.
		fSignature = null;
		fSourceName = null;
	}

	/**
	 * @return Returns the interfaces declared as implemented by this class.
	 *         Interfaces indirectly implemented (extended by the implemented
	 *         interface or implemented by a superclass) are not included.
	 */
	public List<InterfaceType> allInterfaces() {
		if (fAllInterfaces != null) {
			return fAllInterfaces;
		}

		/*
		 * Recursion: The interfaces that it directly implements; All interfaces
		 * that are implemented by its interfaces; If it is a class, all
		 * interfaces that are implemented by its superclass.
		 */
		// The interfaces are maintained in a set, to avoid duplicates.
		// The interfaces of its own (own interfaces() command) are first
		// inserted.
		HashSet<InterfaceType> allInterfacesSet = new HashSet<>(interfaces());

		// All interfaces of the interfaces it implements.
		Iterator<InterfaceType> interfaces = interfaces().iterator();
		InterfaceType inter;
		while (interfaces.hasNext()) {
			inter = interfaces.next();
			allInterfacesSet.addAll(((InterfaceTypeImpl)inter).allInterfaces());
		}

		// If it is a class, all interfaces of it's superclass.
		if (this instanceof ClassType) {
			ClassType superclass = ((ClassType) this).superclass();
			if (superclass != null) {
				allInterfacesSet.addAll(superclass.allInterfaces());
			}
		}

		fAllInterfaces = new ArrayList<>(allInterfacesSet);
		return fAllInterfaces;
	}

	/**
	 * @return Returns JDWP Reference ID.
	 */
	public JdwpReferenceTypeID getRefTypeID() {
		return fReferenceTypeID;
	}

	/**
	 * @return Returns modifier bits.
	 */
	@Override
	public int modifiers() {
		if (fModifierBits != -1)
			return fModifierBits;

		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_MODIFIERS, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			fModifierBits = readInt(
					"modifiers", AccessibleImpl.getModifierStrings(), replyData); //$NON-NLS-1$
			return fModifierBits;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return 0;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * Add methods to a set of methods if they are not overridden, add new
	 * names+signature combinations to set of names+signature combinations.
	 */
	private void addVisibleMethods(List<Method> inheritedMethods, Set<String> nameAndSignatures, List<Method> resultMethods) {
		Iterator<Method> iter = inheritedMethods.iterator();
		Method inheritedMethod;
		while (iter.hasNext()) {
			inheritedMethod = iter.next();
			if (!nameAndSignatures.contains(inheritedMethod.name()
					+ inheritedMethod.signature())) {
				resultMethods.add(inheritedMethod);
			}
		}
	}

	/**
	 * @return Returns a list containing each visible and unambiguous Method in
	 *         this type.
	 */
	@Override
	public List<Method> visibleMethods() {
		if (fVisibleMethods != null)
			return fVisibleMethods;

		/*
		 * Recursion: The methods of its own (own methods() command); All
		 * methods of the interfaces it implements; If it is a class, all
		 * methods of it's superclass.
		 */
		// The name+signature combinations of methods are maintained in a set,
		// to avoid including methods that have been overridden.
		Set<String> namesAndSignatures = new HashSet<>();
		List<Method> visibleMethods = new ArrayList<>();

		// The methods of its own (own methods() command).
		for (Iterator<Method> iter = methods().iterator(); iter.hasNext();) {
			MethodImpl method = (MethodImpl) iter.next();
			namesAndSignatures.add(method.name() + method.signature());
			visibleMethods.add(method);
		}

		// All methods of the interfaces it implements.
		Iterator<InterfaceType> interfaces = interfaces().iterator();
		InterfaceType inter;
		while (interfaces.hasNext()) {
			inter = interfaces.next();
			addVisibleMethods(inter.visibleMethods(), namesAndSignatures,
					visibleMethods);
		}

		// If it is a class, all methods of it's superclass.
		if (this instanceof ClassType) {
			ClassType superclass = ((ClassType) this).superclass();
			if (superclass != null)
				addVisibleMethods(superclass.visibleMethods(),
						namesAndSignatures, visibleMethods);
		}

		fVisibleMethods = visibleMethods;
		return fVisibleMethods;
	}

	/**
	 * @return Returns a list containing each Method declared in this type, and
	 *         its super-classes, implemented interfaces, and/or
	 *         super-interfaces.
	 */
	@Override
	public List<Method> allMethods() {
		if (fAllMethods != null)
			return fAllMethods;

		/*
		 * Recursion: The methods of its own (own methods() command); All
		 * methods of the interfaces it implements; If it is a class, all
		 * methods of it's superclass.
		 */
		// The name+signature combinations of methods are maintained in a set.
		HashSet<Method> resultSet = new HashSet<>();

		// The methods of its own (own methods() command).
		resultSet.addAll(methods());

		// All methods of the interfaces it implements.
		Iterator<InterfaceType> interfaces = interfaces().iterator();
		InterfaceType inter;
		while (interfaces.hasNext()) {
			inter = interfaces.next();
			resultSet.addAll(inter.allMethods());
		}

		// If it is a class, all methods of it's superclass.
		if (this instanceof ClassType) {
			ClassType superclass = ((ClassType) this).superclass();
			if (superclass != null)
				resultSet.addAll(superclass.allMethods());
		}

		fAllMethods = new ArrayList<>(resultSet);
		return fAllMethods;
	}

	/**
	 * @return Returns the interfaces declared as implemented by this class.
	 *         Interfaces indirectly implemented (extended by the implemented
	 *         interface or implemented by a superclass) are not included.
	 */
	public List<InterfaceType> interfaces() {
		if (fInterfaces != null) {
			return fInterfaces;
		}

		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_INTERFACES, this);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.NOT_FOUND:
				// Workaround for problem in J2ME WTK (wireless toolkit)
				// @see Bug 12966
				return Collections.EMPTY_LIST;
			default:
				defaultReplyErrorHandler(replyPacket.errorCode());
			}
			DataInputStream replyData = replyPacket.dataInStream();
			List<InterfaceType> elements = new ArrayList<>();
			int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
			for (int i = 0; i < nrOfElements; i++) {
				InterfaceTypeImpl ref = InterfaceTypeImpl.read(this, replyData);
				if (ref == null) {
					continue;
				}
				elements.add(ref);
			}
			fInterfaces = elements;
			return elements;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * Add fields to a set of fields if they are not overridden, add new field
	 * names to set of field names.
	 */
	private void addVisibleFields(List<Field> newFields, Set<String> names, List<Field> resultFields) {
		Iterator<Field> iter = newFields.iterator();
		FieldImpl field;
		while (iter.hasNext()) {
			field = (FieldImpl) iter.next();
			String name = field.name();
			if (!names.contains(name)) {
				resultFields.add(field);
				names.add(name);
			}
		}
	}

	/**
	 * @return Returns a list containing each visible and unambiguous Field in
	 *         this type.
	 */
	@Override
	public List<Field> visibleFields() {
		if (fVisibleFields != null)
			return fVisibleFields;

		/*
		 * Recursion: The fields of its own (own fields() command); All fields
		 * of the interfaces it implements; If it is a class, all fields of it's
		 * superclass.
		 */
		// The names of fields are maintained in a set, to avoid including
		// fields that have been overridden.
		HashSet<String> fieldNames = new HashSet<>();

		// The fields of its own (own fields() command).
		List<Field> visibleFields = new ArrayList<>();
		addVisibleFields(fields(), fieldNames, visibleFields);

		// All fields of the interfaces it implements.
		Iterator<InterfaceType> interfaces = interfaces().iterator();
		InterfaceType inter;
		while (interfaces.hasNext()) {
			inter = interfaces.next();
			addVisibleFields(inter.visibleFields(), fieldNames, visibleFields);
		}

		// If it is a class, all fields of it's superclass.
		if (this instanceof ClassType) {
			ClassType superclass = ((ClassType) this).superclass();
			if (superclass != null)
				addVisibleFields(superclass.visibleFields(), fieldNames,
						visibleFields);
		}

		fVisibleFields = visibleFields;
		return fVisibleFields;
	}

	/**
	 * @return Returns a list containing each Field declared in this type, and
	 *         its super-classes, implemented interfaces, and/or
	 *         super-interfaces.
	 */
	@Override
	public List<Field> allFields() {
		if (fAllFields != null)
			return fAllFields;

		/*
		 * Recursion: The fields of its own (own fields() command); All fields
		 * of the interfaces it implements; If it is a class, all fields of it's
		 * superclass.
		 */
		// The names of fields are maintained in a set, to avoid including
		// fields that have been inherited double.
		HashSet<Field> resultSet = new HashSet<>();

		// The fields of its own (own fields() command).
		resultSet.addAll(fields());

		// All fields of the interfaces it implements.
		Iterator<InterfaceType> interfaces = interfaces().iterator();
		InterfaceType inter;
		while (interfaces.hasNext()) {
			inter = interfaces.next();
			resultSet.addAll(inter.allFields());
		}

		// If it is a class, all fields of it's superclass.
		if (this instanceof ClassType) {
			ClassType superclass = ((ClassType) this).superclass();
			if (superclass != null)
				resultSet.addAll(superclass.allFields());
		}

		fAllFields = new ArrayList<>(resultSet);
		return fAllFields;
	}

	/**
	 * @return Returns the class loader object which loaded the class
	 *         corresponding to this type.
	 */
	@Override
	public ClassLoaderReference classLoader() {
		if (fClassLoader != null)
			return fClassLoader;

		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_CLASS_LOADER, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			fClassLoader = ClassLoaderReferenceImpl.read(this, replyData);
			return fClassLoader;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns the class object that corresponds to this type in the
	 *         target VM.
	 */
	@Override
	public ClassObjectReference classObject() {
		if (fClassObject != null)
			return fClassObject;

		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_CLASS_OBJECT, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			fClassObject = ClassObjectReferenceImpl.read(this, replyData);
			return fClassObject;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns status of class/interface.
	 */
	protected int status() {
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_STATUS, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			int status = readInt("status", classStatusStrings(), replyData); //$NON-NLS-1$
			return status;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return 0;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns true if initialization failed for this class.
	 */
	@Override
	public boolean failedToInitialize() {
		return (status() & JDWP_CLASS_STATUS_ERROR) != 0;
	}

	/**
	 * @return Returns true if this type has been initialized.
	 */
	@Override
	public boolean isInitialized() {
		return (status() & JDWP_CLASS_STATUS_INITIALIZED) != 0;
	}

	/**
	 * @return Returns true if this type has been prepared.
	 */
	@Override
	public boolean isPrepared() {
		return (status() & JDWP_CLASS_STATUS_PREPARED) != 0;
	}

	/**
	 * @return Returns true if this type has been verified.
	 */
	@Override
	public boolean isVerified() {
		return (status() & JDWP_CLASS_STATUS_VERIFIED) != 0;
	}

	/**
	 * @return Returns the visible Field with the given non-ambiguous name.
	 */
	@Override
	public Field fieldByName(String name) {
		Iterator<Field> iter = visibleFields().iterator();
		while (iter.hasNext()) {
			FieldImpl field = (FieldImpl) iter.next();
			if (field.name().equals(name))
				return field;
		}
		return null;
	}

	/**
	 * @return Returns a list containing each Field declared in this type.
	 */
	@Override
	public List<Field> fields() {
		if (fFields != null) {
			return fFields;
		}

		// Note: Fields are returned in the order they occur in the class file,
		// therefore their
		// order in this list can be used for comparisons.
		initJdwpRequest();
		try {
			boolean withGenericSignature = virtualMachineImpl()
					.isJdwpVersionGreaterOrEqual(1, 5);
			int jdwpCommand = withGenericSignature ? JdwpCommandPacket.RT_FIELDS_WITH_GENERIC
					: JdwpCommandPacket.RT_FIELDS;
			JdwpReplyPacket replyPacket = requestVM(jdwpCommand, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			List<Field> elements = new ArrayList<>();
			int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
			for (int i = 0; i < nrOfElements; i++) {
				FieldImpl elt = FieldImpl.readWithNameSignatureModifiers(this,
						this, withGenericSignature, replyData);
				if (elt == null) {
					continue;
				}
				elements.add(elt);
			}
			fFields = elements;
			return fFields;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns FieldImpl of a field in the reference specified by a
	 *         given fieldID, or null if not found.
	 */
	public FieldImpl findField(JdwpFieldID fieldID) {
		Iterator<Field> iter = fields().iterator();
		while (iter.hasNext()) {
			FieldImpl field = (FieldImpl) iter.next();
			if (field.getFieldID().equals(fieldID))
				return field;
		}
		return null;
	}

	/**
	 * @return Returns MethodImpl of a method in the reference specified by a
	 *         given methodID, or null if not found.
	 */
	public Method findMethod(JdwpMethodID methodID) {
		if (methodID.value() == 0) {
			return new MethodImpl(virtualMachineImpl(), this, methodID,
					JDIMessages.ReferenceTypeImpl_Obsolete_method_1,
					"", null, -1); //$NON-NLS-1$
		}
		if (fMethodTable == null) {
			fMethodTable = new Hashtable<>();
			Iterator<Method> iter = methods().iterator();
			while (iter.hasNext()) {
				MethodImpl method = (MethodImpl) iter.next();
				fMethodTable.put(method.getMethodID(), method);
			}
		}
		return fMethodTable.get(methodID);
	}

	/**
	 * @return Returns the Value of a given static Field in this type.
	 */
	@Override
	public Value getValue(Field field) {
		ArrayList<Field> list = new ArrayList<>(1);
		list.add(field);
		return getValues(list).get(field);
	}

	/**
	 * @return a Map of the requested static Field objects with their Value.
	 */
	@Override
	public Map<Field, Value> getValues(List<? extends Field> fields) {
		// if the field list is empty, nothing to do
		if (fields.isEmpty()) {
			return new HashMap<>();
		}
		// Note that this information should not be cached.
		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			int fieldsSize = fields.size();
			write(this, outData);
			writeInt(fieldsSize, "size", outData); //$NON-NLS-1$
			for (int i = 0; i < fieldsSize; i++) {
				FieldImpl field = (FieldImpl) fields.get(i);
				checkVM(field);
				field.getFieldID().write(outData);
			}

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_GET_VALUES, outBytes);
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			HashMap<Field, Value> map = new HashMap<>();
			int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
			if (nrOfElements != fieldsSize)
				throw new InternalError(
						JDIMessages.ReferenceTypeImpl_Retrieved_a_different_number_of_values_from_the_VM_than_requested_3);

			for (int i = 0; i < nrOfElements; i++) {
				map.put(fields.get(i), ValueImpl.readWithTag(this, replyData));
			}
			return map;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns the hash code value.
	 */
	@Override
	public int hashCode() {
		return fReferenceTypeID.hashCode();
	}

	/**
	 * @return Returns true if two mirrors refer to the same entity in the
	 *         target VM.
	 * @see java.lang.Object#equals(Object)
	 */
	@Override
	public boolean equals(Object object) {
		return object != null
				&& object.getClass().equals(this.getClass())
				&& fReferenceTypeID
						.equals(((ReferenceTypeImpl) object).fReferenceTypeID)
				&& virtualMachine().equals(
						((MirrorImpl) object).virtualMachine());
	}

	/**
	 * @return Returns a negative integer, zero, or a positive integer as this
	 *         {@link ReferenceType} is less than, equal to, or greater than the specified
	 *         {@link ReferenceType}.
	 */
	@Override
	public int compareTo(ReferenceType type) {
		if (type == null || !type.getClass().equals(this.getClass()))
			throw new ClassCastException(JDIMessages.ReferenceTypeImpl_Can__t_compare_reference_type_to_given_object_4);
		return name().compareTo(type.name());
	}

	/**
	 * @return Returns true if the type was declared abstract.
	 */
	@Override
	public boolean isAbstract() {
		return (modifiers() & MODIFIER_ACC_ABSTRACT) != 0;
	}

	/**
	 * @return Returns true if the type was declared final.
	 */
	@Override
	public boolean isFinal() {
		return (modifiers() & MODIFIER_ACC_FINAL) != 0;
	}

	/**
	 * @return Returns true if the type was declared static.
	 */
	@Override
	public boolean isStatic() {
		return (modifiers() & MODIFIER_ACC_STATIC) != 0;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ReferenceType#locationsOfLine(int)
	 */
	@Override
	public List<Location> locationsOfLine(int line) throws AbsentInformationException {
		return locationsOfLine(virtualMachine().getDefaultStratum(), null, line);
	}

	/**
	 * @return Returns a list containing each Method declared directly in this
	 *         type.
	 */
	@Override
	public List<Method> methods() {
		// Note that ArrayReference overwrites this method by returning an empty
		// list.
		if (fMethods != null)
			return fMethods;

		// Note: Methods are returned in the order they occur in the class file,
		// therefore their
		// order in this list can be used for comparisons.
		initJdwpRequest();
		try {
			boolean withGenericSignature = virtualMachineImpl()
					.isJdwpVersionGreaterOrEqual(1, 5);
			int jdwpCommand = withGenericSignature ? JdwpCommandPacket.RT_METHODS_WITH_GENERIC
					: JdwpCommandPacket.RT_METHODS;
			JdwpReplyPacket replyPacket = requestVM(jdwpCommand, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			List<Method> elements = new ArrayList<>();
			int nrOfElements = readInt("elements", replyData); //$NON-NLS-1$
			for (int i = 0; i < nrOfElements; i++) {
				MethodImpl elt = MethodImpl.readWithNameSignatureModifiers(
						this, this, withGenericSignature, replyData);
				if (elt == null) {
					continue;
				}
				elements.add(elt);
			}
			fMethods = elements;
			return fMethods;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns a List containing each visible Method that has the given
	 *         name.
	 */
	@Override
	public List<Method> methodsByName(String name) {
		List<Method> elements = new ArrayList<>();
		Iterator<Method> iter = visibleMethods().iterator();
		while (iter.hasNext()) {
			Method method = iter.next();
			if (method.name().equals(name)) {
				elements.add(method);
			}
		}
		return elements;
	}

	/**
	 * @return Returns a List containing each visible Method that has the given
	 *         name and signature.
	 */
	@Override
	public List<Method> methodsByName(String name, String signature) {
		List<Method> elements = new ArrayList<>();
		Iterator<Method> iter = visibleMethods().iterator();
		while (iter.hasNext()) {
			MethodImpl method = (MethodImpl) iter.next();
			if (method.name().equals(name) && method.signature().equals(signature)) {
				elements.add(method);
			}
		}
		return elements;
	}

	/**
	 * @return Returns the fully qualified name of this type.
	 */
	@Override
	public String name() {
		// Make sure that we know the signature, from which the name is derived.
		if (fName == null) {
			setName(signatureToName(signature()));
		}
		return fName;
	}

	/**
	 * @return Returns the JNI-style signature for this type.
	 */
	@Override
	public String signature() {
		if (fSignature != null) {
			return fSignature;
		}
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_SIGNATURE, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			setSignature(readString("signature", replyData)); //$NON-NLS-1$
			return fSignature;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns a List containing each ReferenceType declared within this
	 *         type.
	 */
	@Override
	public List<ReferenceType> nestedTypes() {
		// Note that the VM gives an empty reply on RT_NESTED_TYPES, therefore
		// we search for the
		// nested types in the loaded types.
		List<ReferenceType> result = new ArrayList<>();
		Iterator<ReferenceType> itr = virtualMachineImpl().allRefTypes();
		while (itr.hasNext()) {
			try {
				ReferenceTypeImpl refType = (ReferenceTypeImpl) itr.next();
				String refName = refType.name();
				if (refName.length() > name().length()
						&& refName.startsWith(name())
						&& refName.charAt(name().length()) == '$') {
					result.add(refType);
				}
			} catch (ClassNotPreparedException e) {
				continue;
			}
		}
		return result;
	}

	/**
	 * @return Returns an identifying name for the source corresponding to the
	 *         declaration of this type.
	 */
	@Override
	public String sourceName() throws AbsentInformationException {
		// sourceNames list in never empty, an AbsentInformationException is
		// thrown
		// if the source name is not known.
		return sourceNames(virtualMachine().getDefaultStratum())
				.get(0);
	}

	/**
	 * @return Returns the CRC-32 of the given reference type, undefined if
	 *         unknown.
	 */
	@Override
	public int getClassFileVersion() {
		virtualMachineImpl().checkHCRSupported();
		if (fGotClassFileVersion)
			return fClassFileVersion;

		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.HCR_GET_CLASS_VERSION, this);
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			fIsHCREligible = readBoolean("HCR eligible", replyData); //$NON-NLS-1$
			fIsVersionKnown = readBoolean("version known", replyData); //$NON-NLS-1$
			fClassFileVersion = readInt("class file version", replyData); //$NON-NLS-1$
			fGotClassFileVersion = true;
			return fClassFileVersion;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return 0;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns whether the CRC-32 of the given reference type is known.
	 */
	@Override
	public boolean isVersionKnown() {
		getClassFileVersion();
		return fIsVersionKnown;
	}

	/**
	 * @return Returns whether the reference type is HCR-eligible.
	 */
	@Override
	public boolean isHCREligible() {
		getClassFileVersion();
		return fIsHCREligible;
	}

	/**
	 * Writes JDWP representation.
	 */
	public void write(MirrorImpl target, DataOutputStream out)
			throws IOException {
		fReferenceTypeID.write(out);
		if (target.fVerboseWriter != null)
			target.fVerboseWriter.println(
					"referenceType", fReferenceTypeID.value()); //$NON-NLS-1$
	}

	/**
	 * Writes representation of null referenceType.
	 */
	public static void writeNull(MirrorImpl target, DataOutputStream out)
			throws IOException {
		// create null id
		JdwpReferenceTypeID ID = new JdwpReferenceTypeID(
				target.virtualMachineImpl());
		ID.write(out);
		if (target.fVerboseWriter != null)
			target.fVerboseWriter.println("referenceType", ID.value()); //$NON-NLS-1$
	}

	/**
	 * Writes JDWP representation.
	 */
	public void writeWithTag(MirrorImpl target, DataOutputStream out)
			throws IOException {
		target.writeByte(typeTag(), "type tag", JdwpID.typeTagMap(), out); //$NON-NLS-1$
		write(target, out);
	}

	/**
	 * @return Reads JDWP representation and returns new or cached instance.
	 */
	public static ReferenceTypeImpl readWithTypeTag(MirrorImpl target,
			DataInputStream in) throws IOException {
		byte typeTag = target.readByte("type tag", JdwpID.typeTagMap(), in); //$NON-NLS-1$
		switch (typeTag) {
		case 0:
			return null;
		case ArrayTypeImpl.typeTag:
			return ArrayTypeImpl.read(target, in);
		case ClassTypeImpl.typeTag:
			return ClassTypeImpl.read(target, in);
		case InterfaceTypeImpl.typeTag:
			return InterfaceTypeImpl.read(target, in);
		}
		throw new InternalException(
				JDIMessages.ReferenceTypeImpl_Invalid_ReferenceTypeID_tag_encountered___8
						+ typeTag);
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ReferenceType#allLineLocations()
	 */
	@Override
	public List<Location> allLineLocations() throws AbsentInformationException {
		return allLineLocations(virtualMachine().getDefaultStratum(), null);
	}

	/**
	 * @return Reads JDWP representation and returns new or cached instance.
	 */
	public static ReferenceTypeImpl readWithTypeTagAndSignature(
			MirrorImpl target, boolean withGenericSignature, DataInputStream in)
			throws IOException {
		byte typeTag = target.readByte("type tag", JdwpID.typeTagMap(), in); //$NON-NLS-1$
		switch (typeTag) {
		case 0:
			return null;
		case ArrayTypeImpl.typeTag:
			return ArrayTypeImpl.readWithSignature(target,
					withGenericSignature, in);
		case ClassTypeImpl.typeTag:
			return ClassTypeImpl.readWithSignature(target,
					withGenericSignature, in);
		case InterfaceTypeImpl.typeTag:
			return InterfaceTypeImpl.readWithSignature(target,
					withGenericSignature, in);
		}
		throw new InternalException(
				JDIMessages.ReferenceTypeImpl_Invalid_ReferenceTypeID_tag_encountered___8
						+ typeTag);
	}

	/**
	 * @return Returns new instance based on signature and classLoader.
	 * @throws ClassNotLoadedException
	 *             when the ReferenceType has not been loaded by the specified
	 *             class loader.
	 */
	public static TypeImpl create(VirtualMachineImpl vmImpl, String signature,
			ClassLoaderReference classLoader) throws ClassNotLoadedException {
		ReferenceTypeImpl refTypeBootstrap = null;
		List<ReferenceType> classes = vmImpl.classesBySignature(signature);
		ReferenceTypeImpl type;
		Iterator<ReferenceType> iter = classes.iterator();
		while (iter.hasNext()) {
			// First pass. Look for a class loaded by the given class loader
			type = (ReferenceTypeImpl) iter.next();
			if (type.classLoader() == null) { // bootstrap classloader
				if (classLoader == null) {
					return type;
				}
				refTypeBootstrap = type;
			}
			if (classLoader != null && classLoader.equals(type.classLoader())) {
				return type;
			}
		}
		// If no ReferenceType is found with the specified classloader, but
		// there is one with the
		// bootstrap classloader, the latter is returned.
		if (refTypeBootstrap != null) {
			return refTypeBootstrap;
		}

		List<ReferenceType> visibleTypes;
		iter = classes.iterator();
		while (iter.hasNext()) {
			// Second pass. Look for a class that is visible to
			// the given class loader
			type = (ReferenceTypeImpl) iter.next();
			visibleTypes = classLoader.visibleClasses();
			Iterator<ReferenceType> visibleIter = visibleTypes.iterator();
			while (visibleIter.hasNext()) {
				if (type.equals(visibleIter.next())) {
					return type;
				}
			}
		}

		throw new ClassNotLoadedException(classSignatureToName(signature),
				JDIMessages.ReferenceTypeImpl_Type_has_not_been_loaded_10);
	}

	/**
	 * Retrieves constant mappings.
	 */
	public static void getConstantMaps() {
		if (fgClassStatusStrings != null) {
			return;
		}

		java.lang.reflect.Field[] fields = ReferenceTypeImpl.class
				.getDeclaredFields();
		fgClassStatusStrings = new String[32];

		for (java.lang.reflect.Field field : fields) {
			if ((field.getModifiers() & Modifier.PUBLIC) == 0
					|| (field.getModifiers() & Modifier.STATIC) == 0
					|| (field.getModifiers() & Modifier.FINAL) == 0) {
				continue;
			}

			String name = field.getName();
			if (!name.startsWith("JDWP_CLASS_STATUS_")) { //$NON-NLS-1$
				continue;
			}

			name = name.substring(18);

			try {
				int value = field.getInt(null);

				for (int j = 0; j < fgClassStatusStrings.length; j++) {
					if ((1 << j & value) != 0) {
						fgClassStatusStrings[j] = name;
						break;
					}
				}
			} 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 String[] classStatusStrings() {
		getConstantMaps();
		return fgClassStatusStrings;
	}

	/**
	 * @see TypeImpl#createNullValue()
	 */
	@Override
	public Value createNullValue() {
		return null;
	}

	/**
	 * @see ReferenceType#sourceNames(String)
	 */
	@Override
	public List<String> sourceNames(String stratumId) throws AbsentInformationException {
		List<String> list = new ArrayList<>();
		Stratum stratum = getStratum(stratumId);
		if (stratum != null) {
			// return the source names defined for this stratum in the SMAP.
			List<FileInfo> fileInfos = stratum.fFileInfos;
			if (fileInfos.isEmpty()) {
				throw new AbsentInformationException(
						JDIMessages.ReferenceTypeImpl_30);
			}
			for (Iterator<FileInfo> iter = stratum.fFileInfos.iterator(); iter.hasNext();) {
				list.add(iter.next().fFileName);
			}
			return list;
		}
		// Java stratum
		if (fSourceName == null) {
			getSourceName();
		}
		list.add(fSourceName);
		return list;
	}

	/**
	 * @see ReferenceType#sourcePaths(String)
	 */
	@Override
	public List<String> sourcePaths(String stratumId) throws AbsentInformationException {
		List<String> list = new ArrayList<>();
		Stratum stratum = getStratum(stratumId);
		if (stratum != null) {
			// return the source paths defined for this stratum in the SMAP.
			for (Iterator<FileInfo> iter = stratum.fFileInfos.iterator(); iter.hasNext();) {
				FileInfo fileInfo = iter.next();
				String path = fileInfo.fAbsoluteFileName;
				if (path == null) {
					path = getPath(fileInfo.fFileName);
				}
				list.add(path);
			}
			return list;
		}
		// Java stratum
		if (fSourceName == null) {
			getSourceName();
		}
		list.add(getPath(fSourceName));
		return list;
	}

	/**
	 * @see ReferenceType#sourceDebugExtension()
	 */
	@Override
	public String sourceDebugExtension() throws AbsentInformationException {
		if (isSourceDebugExtensionAvailable()) {
			return fSmap;
		}
		if (!virtualMachine().canGetSourceDebugExtension()) {
			throw new UnsupportedOperationException("1"); //$NON-NLS-1$
		}
		throw new AbsentInformationException();
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ReferenceType#allLineLocations(java.lang.String, java.lang.String)
	 */
	@Override
	public List<Location> allLineLocations(String stratum, String sourceName) throws AbsentInformationException {
		Iterator<Method> allMethods = methods().iterator();
		if (stratum == null) { // if stratum not defined use the default stratum
			stratum = defaultStratum();
		}
		List<Location> allLineLocations = null;
		Map<String, List<Location>> sourceNameAllLineLocations = null;
		if (fStratumAllLineLocations == null) { // the stratum map doesn't
												// exist, create it
			fStratumAllLineLocations = new HashMap<>();
		} else {
			// get the source name map
			sourceNameAllLineLocations = fStratumAllLineLocations.get(stratum);
		}
		if (sourceNameAllLineLocations == null) { // the source name map doesn't
													// exist, create it
			sourceNameAllLineLocations = new HashMap<>();
			fStratumAllLineLocations.put(stratum, sourceNameAllLineLocations);
		} else {
			// get the line locations
			allLineLocations = sourceNameAllLineLocations.get(sourceName);
		}
		if (allLineLocations == null) { // the line locations are not known, compute and store them
			allLineLocations = new ArrayList<>();
			boolean hasLineInformation = false;
			AbsentInformationException exception = null;
			while (allMethods.hasNext()) {
				MethodImpl method = (MethodImpl) allMethods.next();
				if (method.isAbstract() || method.isNative()) {
					continue;
				}
				try {
					allLineLocations.addAll(method.allLineLocations(stratum, sourceName));
					hasLineInformation = true;
				} catch (AbsentInformationException e) {
					exception = e;
				}
			}
			if (!hasLineInformation && exception != null) {
				throw exception;
			}
			sourceNameAllLineLocations.put(sourceName, allLineLocations);
		}
		return allLineLocations;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ReferenceType#locationsOfLine(java.lang.String, java.lang.String, int)
	 */
	@Override
	public List<Location> locationsOfLine(String stratum, String sourceName, int lineNumber) throws AbsentInformationException {
		Iterator<Method> allMethods = methods().iterator();
		List<Location> locations = new ArrayList<>();
		boolean hasLineInformation = false;
		AbsentInformationException exception = null;
		while (allMethods.hasNext()) {
			MethodImpl method = (MethodImpl) allMethods.next();
			if (method.isAbstract() || method.isNative()) {
				continue;
			}
			// one line in the input source can be translate in multiple lines
			// in different
			// methods in the output source. We need all these locations.
			try {
				locations.addAll(locationsOfLine(stratum, sourceName, lineNumber, method));
				hasLineInformation = true;
			} catch (AbsentInformationException e) {
				exception = e;
			}
		}
		if (!hasLineInformation && exception != null) {
			throw exception;
		}
		return locations;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ReferenceType#availableStrata()
	 */
	@Override
	public List<String> availableStrata() {
		List<String> list = new ArrayList<>();
		// The strata defined in the SMAP.
		if (isSourceDebugExtensionAvailable()) {
			list.addAll(fStrata.keySet());
		}
		// plus the Java stratum
		list.add(VirtualMachineImpl.JAVA_STRATUM_NAME);
		return list;
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ReferenceType#defaultStratum()
	 */
	@Override
	public String defaultStratum() {
		if (isSourceDebugExtensionAvailable()) {
			return fDefaultStratumId;
		}
		// if not defined, return Java.
		return VirtualMachineImpl.JAVA_STRATUM_NAME;
	}

	/**
	 * Generate a source path from the given source name. The returned string is
	 * the package name of this type converted to a platform dependent path
	 * followed by the given source name. For example, on a Unix platform, the
	 * type org.my.TestJsp with the source name test.jsp would return
	 * "org/my/test.jsp".
	 */
	private String getPath(String sourceName) {
		String name = name();
		int lastDotOffset = name.lastIndexOf('.');
		if (lastDotOffset == -1) {
			return sourceName;
		}
		char fileSeparator = System.getProperty("file.separator").charAt(0); //$NON-NLS-1$
		return name.substring(0, lastDotOffset).replace('.', fileSeparator)
				+ fileSeparator + sourceName;
	}

	/**
	 * Return the stratum object for this stratum Id. If the the specified
	 * stratum id is not defined for this reference type, return the stratum
	 * object for the default stratum. If the specified stratum id (or the
	 * default stratum id, if the specified stratum id is not defined) is
	 * <code>Java</code>, return <code>null</code>.
	 */
	private Stratum getStratum(String stratumId) {
		if (!VirtualMachineImpl.JAVA_STRATUM_NAME.equals(stratumId)
				&& isSourceDebugExtensionAvailable()) {
			if (stratumId == null || !fStrata.keySet().contains(stratumId)) {
				stratumId = fDefaultStratumId;
			}
			if (!VirtualMachineImpl.JAVA_STRATUM_NAME.equals(stratumId)) {
				return fStrata.get(stratumId);
			}
		}
		return null;
	}

	/**
	 * Get the source debug extension from the VM.
	 *
	 * @throws AbsentInformationException
	 */
	private void getSourceDebugExtension() throws AbsentInformationException {
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_SOURCE_DEBUG_EXTENSION, this);
			if (replyPacket.errorCode() == JdwpReplyPacket.ABSENT_INFORMATION) {
				throw new AbsentInformationException(
						JDIMessages.ReferenceTypeImpl_31);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			fSmap = readString(JDIMessages.ReferenceTypeImpl_32, replyData);
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
		} finally {
			handledJdwpRequest();
		}
		// TODO: remove the workaround when the J9SC20030415 bug is fixed (see
		// bug 96485 of the vendor bug system).
		// Workaround to a J9SC bug. It returns an empty string instead of a
		// ABSENT_INFORMATION
		// error if the source debug extension is not available.
		if ("".equals(fSmap)) { //$NON-NLS-1$
			throw new AbsentInformationException(
					JDIMessages.ReferenceTypeImpl_31);
		}
		// parse the source map.
		fStrata = new HashMap<>();
		SourceDebugExtensionParser.parse(fSmap, this);
	}

	/**
	 * Get the name of the Java source file from the VM.
	 *
	 * @throws AbsentInformationException
	 */
	private void getSourceName() throws AbsentInformationException {
		if (fSourceName != null || isSourceDebugExtensionAvailable()) {
			return;
		}
		initJdwpRequest();
		try {
			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_SOURCE_FILE, this);
			if (replyPacket.errorCode() == JdwpReplyPacket.ABSENT_INFORMATION) {
				throw new AbsentInformationException(
						JDIMessages.ReferenceTypeImpl_Source_name_is_not_known_7);
			}

			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			fSourceName = readString("source name", replyData); //$NON-NLS-1$
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * Check in the source debug extension is available. To call before doing
	 * operations which need data from the SMAP. Return <code>false</code> if
	 * the source debug extension is not available for any reason.
	 * <code>true</code> indicates that the source debug extension is available
	 * and the information has been parsed and stored in the maps and lists.
	 */
	private synchronized boolean isSourceDebugExtensionAvailable() {
		if (!fSourceDebugExtensionAvailable) {
			return false;
		}
		if (!virtualMachine().canGetSourceDebugExtension()) {
			fSourceDebugExtensionAvailable = false;
			return false;
		}
		if (fSmap == null) {
			try {
				getSourceDebugExtension();
			} catch (AbsentInformationException e) {
				fSourceDebugExtensionAvailable = false;
				return false;
			}
		}
		return true;
	}

	/**
	 * Set the output file name, i.e. the .java file used to generate the
	 * bytecode.
	 */
	protected void setOutputFileName(String outputFileName) {
		fSourceName = outputFileName;
	}

	/**
	 * Set the default stratum. This stratum will be used for the method on
	 * strata related data, but with no stratum parameter.
	 */
	protected void setDefaultStratumId(String defaultStratumId) {
		fDefaultStratumId = defaultStratumId;
	}

	/**
	 * Add a new stratum to this type.
	 */
	protected void addStratum(Stratum stratum) {
		fStrata.put(stratum.fId, stratum);
	}

	/**
	 * Return the name of the input source file of which the given code index is
	 * part of the translation, for this stratum. If the code at the given index
	 * is not a part of the translation of the given stratum code, return the
	 * name of the primary input source file.
	 *
	 * @param codeIndex
	 *            the index of the code.
	 * @param method
	 *            the method where is the code.
	 * @param stratumId
	 */
	protected String sourceName(long codeIndex, MethodImpl method,
			String stratumId) throws AbsentInformationException {
		Stratum stratum = getStratum(stratumId);
		if (stratum != null) {
			FileInfo fileInfo = fileInfo(codeIndex, method, stratum);
			if (fileInfo != null) {
				return fileInfo.fFileName;
			}
		}
		// Java stratum
		if (fSourceName == null) {
			getSourceName();
		}
		return fSourceName;
	}

	/**
	 * Return the FileInfo object of the input source file of which the given
	 * code index is part of the translation, for this stratum. If the code at
	 * the given index is not a part of the translation of the given stratum
	 * code, return the FileInfo of the primary input source file.
	 *
	 * @param codeIndex
	 *            the index of the code.
	 * @param method
	 *            the method where is the code.
	 * @param stratum
	 */
	private FileInfo fileInfo(long codeIndex, MethodImpl method, Stratum stratum) {
		int fileId = stratum.fPrimaryFileId;
		if (stratum.fFileInfos.size() > 1) {
			List<int[]> lineInfos = null;
			try {
				lineInfos = lineInfos(codeIndex, method, stratum);
			} catch (AbsentInformationException e) {
				// nothing to do, use the primary file id.
			}
			if (lineInfos != null) {
				fileId = lineInfos.get(0)[0];
			}
		}
		for (Iterator<FileInfo> iter = stratum.fFileInfos.iterator(); iter.hasNext();) {
			FileInfo fileInfo = iter.next();
			if (fileInfo.fFileId == fileId) {
				return fileInfo;
			}
		}
		// should never return null
		return null;
	}

	/**
	 * Return the list of line number in the input files of the stratum
	 * associated with the code at the given address.
	 *
	 * @param codeIndex
	 *            the index of the code.
	 * @param method
	 *            the method where is the code.
	 * @param stratum
	 * @return List of int[2]: [fileId, inputLineNumber]
	 */
	private List<int[]> lineInfos(long codeIndex, MethodImpl method, Stratum stratum) throws AbsentInformationException {
		int outputLineNumber = -1;
		try {
			outputLineNumber = method.javaStratumLineNumber(codeIndex);
		} catch (NativeMethodException e) { // Occurs in SUN VM.
			return null;
		}
		if (outputLineNumber != -1) {
			return stratum.getInputLineInfos(outputLineNumber);
		}
		return null;
	}

	/**
	 * Return the path of the input source file of which the given code index is
	 * part of the translation, for this stratum. If the code at the given index
	 * is not a part of the translation of the given stratum code, return the
	 * path of the primary input source file.
	 *
	 * @param codeIndex
	 *            the index of the code.
	 * @param method
	 *            the method where is the code.
	 * @param stratumId
	 */
	protected String sourcePath(long codeIndex, MethodImpl method,
			String stratumId) throws AbsentInformationException {
		Stratum stratum = getStratum(stratumId);
		if (stratum != null) {
			FileInfo fileInfo = fileInfo(codeIndex, method, stratum);
			if (fileInfo != null) {
				String path = fileInfo.fAbsoluteFileName;
				if (path == null) {
					return getPath(fileInfo.fFileName);
				}
				return path;
			}
		}
		// Java stratum
		if (fSourceName == null) {
			getSourceName();
		}
		return getPath(fSourceName);
	}

	/**
	 * Return the number of the line of which the given code index is part of
	 * the translation, for this stratum.
	 *
	 * @param codeIndex
	 *            the index of the code.
	 * @param method
	 *            the method where is the code.
	 * @param stratumId
	 */
	protected int lineNumber(long codeIndex, MethodImpl method, String stratumId) {
		Stratum stratum = getStratum(stratumId);
		try {
			if (stratum != null) {
				List<int[]> lineInfos = lineInfos(codeIndex, method, stratum);
				if (lineInfos != null) {
					return lineInfos.get(0)[1];
				}
				return LocationImpl.LINE_NR_NOT_AVAILABLE;
			}
			// Java stratum
			try {
				return method.javaStratumLineNumber(codeIndex);
			} catch (NativeMethodException e) { // Occurs in SUN VM.
				return LocationImpl.LINE_NR_NOT_AVAILABLE;
			}
		} catch (AbsentInformationException e) {
			return LocationImpl.LINE_NR_NOT_AVAILABLE;
		}
	}

	/**
	 * Return the location which are part of the translation of the given line,
	 * in the given stratum in the source file with the given source name. If
	 * sourceName is <code>null</code>, return the locations for all source file
	 * in the given stratum. The returned location are in the given method.
	 *
	 * @param stratumId
	 *            the stratum id.
	 * @param sourceName
	 *            the name of the source file.
	 * @param lineNumber
	 *            the number of the line.
	 * @param method
	 * @throws AbsentInformationException
	 *             if the specified sourceName is not valid.
	 */
	public List<Location> locationsOfLine(String stratumId, String sourceName, int lineNumber, MethodImpl method)	throws AbsentInformationException {
		Stratum stratum = getStratum(stratumId);
		List<Integer> javaLines = new ArrayList<>();
		if (stratum != null) {
			boolean found = false;
			for (Iterator<FileInfo> iter = stratum.fFileInfos.iterator(); iter.hasNext() && !found;) {
				FileInfo fileInfo = iter.next();
				if (sourceName == null || (found = sourceName.equals(fileInfo.fFileName))) {
					javaLines.addAll(fileInfo.getOutputLinesForLine(lineNumber));
				}
			}
			if (sourceName != null && !found) {
				throw new AbsentInformationException(JDIMessages.ReferenceTypeImpl_34);
			}
		} else { // Java stratum
			javaLines.add(new Integer(lineNumber));
		}
		return method.javaStratumLocationsOfLines(javaLines);
	}

	/**
	 * Return the locations of all lines in the given source file of the given
	 * stratum which are included in the given method. If sourceName is
	 * <code>null</code>, return the locations for all source file in the given
	 * stratum.
	 *
	 * @param stratumId
	 *            the stratum id
	 * @param sourceName
	 *            the name of the source file
	 * @param method
	 * @param codeIndexTable
	 *            the list of code indexes for the method, as get from the
	 *            VM/JDWP
	 * @param javaStratumLineNumberTable
	 *            the list of line numbers in the java stratum for the method,
	 *            as get from the VM/JDWP
	 * @return
	 */
	public List<Location> allLineLocations(String stratumId, String sourceName,
			MethodImpl method, long[] codeIndexTable,
			int[] javaStratumLineNumberTable) throws AbsentInformationException {
		Stratum stratum = getStratum(stratumId);
		if (stratum != null) {
			int[][] lineInfoTable = new int[codeIndexTable.length][];
			if (sourceName == null) {
				int lastIndex = 0;
				for (int i = 0, length = javaStratumLineNumberTable.length; i < length; i++) {
					// for each executable line in the java source, get the
					// associated lines in the stratum source
					List<int[]> lineInfos = stratum.getInputLineInfos(javaStratumLineNumberTable[i]);
					if (lineInfos != null) {
						int[] lineInfo = lineInfos.get(0);
						if (!lineInfo.equals(lineInfoTable[lastIndex])) {
							lineInfoTable[i] = lineInfo;
							lastIndex = i;
						}
					}
				}
			} else { // sourceName != null
				FileInfo fileInfo = stratum.getFileInfo(sourceName);
				if (fileInfo == null) {
					throw new AbsentInformationException(JDIMessages.ReferenceTypeImpl_34);
				}
				int fileId = fileInfo.fFileId;
				int lastIndex = 0;
				for (int i = 0, length = javaStratumLineNumberTable.length; i < length; i++) {
					List<int[]> lineInfos = stratum.getInputLineInfos(javaStratumLineNumberTable[i]);
					if (lineInfos != null) {
						for (Iterator<int[]> iter = lineInfos.iterator(); iter.hasNext();) {
							int[] lineInfo = iter.next();
							if (lineInfo[0] == fileId) {
								if (!lineInfo.equals(lineInfoTable[lastIndex])) {
									lineInfoTable[i] = lineInfo;
									lastIndex = i;
								}
								break;
							}
						}
					}
				}
			}
			List<Location> locations = new ArrayList<>();
			for (int i = 0, length = lineInfoTable.length; i < length; i++) {
				if (lineInfoTable[i] != null) {
					locations.add(new LocationImpl(virtualMachineImpl(), method, codeIndexTable[i]));
				}
			}
			return locations;
		}
		// Java stratum
		List<Location> result = new ArrayList<>();
		for (long element : codeIndexTable) {
			result.add(new LocationImpl(virtualMachineImpl(), method, element));
		}
		return result;
	}

	/*
	 * @since 3.0
	 *
	 * @since java 1.5
	 */
	@Override
	public String genericSignature() {
		if (fGenericSignatureKnown) {
			return fGenericSignature;
		}
		if (virtualMachineImpl().isJdwpVersionGreaterOrEqual(1, 5)) {
			initJdwpRequest();
			try {
				JdwpReplyPacket replyPacket = requestVM(
						JdwpCommandPacket.RT_SIGNATURE_WITH_GENERIC, this);
				defaultReplyErrorHandler(replyPacket.errorCode());
				DataInputStream replyData = replyPacket.dataInStream();
				setSignature(readString("signature", replyData)); //$NON-NLS-1$
				fGenericSignature = readString("generic signature", replyData); //$NON-NLS-1$
				if (fGenericSignature.length() == 0) {
					fGenericSignature = null;
				}
				fGenericSignatureKnown = true;
			} catch (IOException e) {
				defaultIOExceptionHandler(e);
				return null;
			} finally {
				handledJdwpRequest();
			}
		} else {
			fGenericSignatureKnown = true;
		}
		return fGenericSignature;
	}

	/**
	 * if genericSignature is <code>null</code>, the generic signature is set to
	 * not-known (genericSignature() will ask the VM for the generic signature)
	 * if genericSignature is an empty String, the generic signature is set to
	 * no-generic-signature (genericSignature() will return null) if
	 * genericSignature is an non-empty String, the generic signature is set to
	 * the specified value (genericSignature() will return the specified value)
	 *
	 * @since 3.0
	 */
	public void setGenericSignature(String genericSignature) {
		if (genericSignature == null) {
			fGenericSignature = null;
			fGenericSignatureKnown = false;
		} else {
			if (genericSignature.length() == 0) {
				fGenericSignature = null;
			} else {
				fGenericSignature = genericSignature;
			}
			fGenericSignatureKnown = true;
		}
	}

	/* (non-Javadoc)
	 * @see com.sun.jdi.ReferenceType#instances(long)
	 */
	@Override
	public List<ObjectReference> instances(long maxInstances) {
		try {
			int max = (int) maxInstances;
			if (maxInstances >= Integer.MAX_VALUE) {
				max = Integer.MAX_VALUE;
			}
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			write(this, outData);
			writeInt(max, "max instances", outData); //$NON-NLS-1$

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_INSTANCES, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_OBJECT:
			case JdwpReplyPacket.INVALID_CLASS:
				throw new ObjectCollectedException(
						JDIMessages.class_or_object_not_known);
			case JdwpReplyPacket.NOT_IMPLEMENTED:
				throw new UnsupportedOperationException(
						JDIMessages.ReferenceTypeImpl_27);
			case JdwpReplyPacket.ILLEGAL_ARGUMENT:
				throw new IllegalArgumentException(
						JDIMessages.ReferenceTypeImpl_26);
			case JdwpReplyPacket.VM_DEAD:
				throw new VMDisconnectedException(JDIMessages.vm_dead);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			int elements = readInt("element count", replyData); //$NON-NLS-1$
			if (max > 0 && elements > max) {
				elements = max;
			}
			ArrayList<ObjectReference> list = new ArrayList<>();
			for (int i = 0; i < elements; i++) {
				list.add((ObjectReference) ValueImpl.readWithTag(this, replyData));
			}
			return list;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @see com.sun.jdi.ReferenceType#majorVersion()
	 * @since 3.3
	 */
	@Override
	public int majorVersion() {
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			getRefTypeID().write(outData);

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_CLASS_VERSION, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_CLASS:
			case JdwpReplyPacket.INVALID_OBJECT:
				throw new ObjectCollectedException(
						JDIMessages.class_or_object_not_known);
			case JdwpReplyPacket.ABSENT_INFORMATION:
				return 0;
			case JdwpReplyPacket.NOT_IMPLEMENTED:
				throw new UnsupportedOperationException(
						JDIMessages.ReferenceTypeImpl_no_class_version_support24);
			case JdwpReplyPacket.VM_DEAD:
				throw new VMDisconnectedException(JDIMessages.vm_dead);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			return readInt("major version", replyData); //$NON-NLS-1$
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return 0;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @see com.sun.jdi.ReferenceType#minorVersion()
	 * @since 3.3
	 */
	@Override
	public int minorVersion() {
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			getRefTypeID().write(outData);

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_CLASS_VERSION, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_CLASS:
			case JdwpReplyPacket.INVALID_OBJECT:
				throw new ObjectCollectedException(
						JDIMessages.class_or_object_not_known);
			case JdwpReplyPacket.ABSENT_INFORMATION:
				return 0;
			case JdwpReplyPacket.NOT_IMPLEMENTED:
				throw new UnsupportedOperationException(
						JDIMessages.ReferenceTypeImpl_no_class_version_support24);
			case JdwpReplyPacket.VM_DEAD:
				throw new VMDisconnectedException(JDIMessages.vm_dead);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			readInt("major version", replyData); //$NON-NLS-1$
			return readInt("minor version", replyData); //$NON-NLS-1$
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return 0;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @see com.sun.jdi.ReferenceType#constantPoolCount()
	 * @since 3.3
	 */
	@Override
	public int constantPoolCount() {
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			this.getRefTypeID().write(outData);

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_CONSTANT_POOL, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_CLASS:
			case JdwpReplyPacket.INVALID_OBJECT:
				throw new ObjectCollectedException(
						JDIMessages.class_or_object_not_known);
			case JdwpReplyPacket.ABSENT_INFORMATION:
				return 0;
			case JdwpReplyPacket.NOT_IMPLEMENTED:
				throw new UnsupportedOperationException(
						JDIMessages.ReferenceTypeImpl_no_constant_pool_support);
			case JdwpReplyPacket.VM_DEAD:
				throw new VMDisconnectedException(JDIMessages.vm_dead);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			return readInt("pool count", replyData); //$NON-NLS-1$
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return 0;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @see com.sun.jdi.ReferenceType#constantPool()
	 * @since 3.3
	 */
	@Override
	public byte[] constantPool() {
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			this.getRefTypeID().write(outData);

			JdwpReplyPacket replyPacket = requestVM(
					JdwpCommandPacket.RT_CONSTANT_POOL, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_CLASS:
			case JdwpReplyPacket.INVALID_OBJECT:
				throw new ObjectCollectedException(
						JDIMessages.class_or_object_not_known);
			case JdwpReplyPacket.ABSENT_INFORMATION:
				return new byte[0];
			case JdwpReplyPacket.NOT_IMPLEMENTED:
				throw new UnsupportedOperationException(
						JDIMessages.ReferenceTypeImpl_no_constant_pool_support);
			case JdwpReplyPacket.VM_DEAD:
				throw new VMDisconnectedException(JDIMessages.vm_dead);
			}
			defaultReplyErrorHandler(replyPacket.errorCode());

			DataInputStream replyData = replyPacket.dataInStream();
			readInt("pool count", replyData); //$NON-NLS-1$
			int bytes = readInt("byte count", replyData); //$NON-NLS-1$
			byte[] array = new byte[bytes];
			for (int i = 0; i < bytes; i++) {
				array[i] = readByte("byte read", replyData); //$NON-NLS-1$
			}
			return array;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

	/**
	 * @return Returns Jdwp version of given options.
	 */
	protected int optionsToJdwpOptions(int options) {
		int jdwpOptions = 0;
		if ((options & ClassType.INVOKE_SINGLE_THREADED) != 0)
			jdwpOptions |= MethodImpl.INVOKE_SINGLE_THREADED_JDWP;
		return jdwpOptions;
	}


	/**
	 * Invoke static method on class or interface type
	 *
	 * @param thread the debugger thread in which to invoke
	 * @param method the resolved chosed Method to invoke
	 * @param arguments the list of Values to supply as arguments for the method, assigned to arguments in the order they appear in the method signature.
	 * @param options the integer bit flags
	 * @param command the JWDP command to invoke
	 * @return a Value representing the method's return value.
	 * @throws InvalidTypeException If the arguments do not match
	 * @throws ClassNotLoadedException if any argument type has not yet been loaded in the VM
	 * @throws IncompatibleThreadStateException if the specified thread has not been suspended
	 * @throws InvocationException if the method invocation resulted in an exception
	 */
	protected Value invokeMethod(ThreadReference thread, Method method, List<? extends Value> arguments, int options, int command) throws InvalidTypeException,
			ClassNotLoadedException, IncompatibleThreadStateException,
			InvocationException {
		checkVM(thread);
		checkVM(method);
		ThreadReferenceImpl threadImpl = (ThreadReferenceImpl) thread;
		MethodImpl methodImpl = (MethodImpl) method;

		// Perform some checks for IllegalArgumentException.
		if (!visibleMethods().contains(method))
			throw new IllegalArgumentException(
					JDIMessages.ClassTypeImpl_Class_does_not_contain_given_method_1);
		if (method.argumentTypeNames().size() != arguments.size())
			throw new IllegalArgumentException(
					JDIMessages.ClassTypeImpl_Number_of_arguments_doesn__t_match_2);
		if (method.isConstructor() || method.isStaticInitializer())
			throw new IllegalArgumentException(
					JDIMessages.ClassTypeImpl_Method_is_constructor_or_intitializer_3);

		// check the type and the VM of the arguments. Convert the values if
		// needed
		List<Value> checkedArguments = ValueImpl.checkValues(arguments, method.argumentTypes(), virtualMachineImpl());

		initJdwpRequest();
		try {
			ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
			DataOutputStream outData = new DataOutputStream(outBytes);
			write(this, outData);
			threadImpl.write(this, outData);
			methodImpl.write(this, outData);

			writeInt(checkedArguments.size(), "size", outData); //$NON-NLS-1$
			Iterator<Value> iter = checkedArguments.iterator();
			while (iter.hasNext()) {
				Value elt = iter.next();
				if (elt instanceof ValueImpl) {
					((ValueImpl)elt).writeWithTag(this, outData);
				} else {
					ValueImpl.writeNullWithTag(this, outData);
				}
			}

			writeInt(optionsToJdwpOptions(options),
					"options", MethodImpl.getInvokeOptions(), outData); //$NON-NLS-1$

			JdwpReplyPacket replyPacket = requestVM(
					command, outBytes);
			switch (replyPacket.errorCode()) {
			case JdwpReplyPacket.INVALID_METHODID:
				throw new IllegalArgumentException();
			case JdwpReplyPacket.TYPE_MISMATCH:
				throw new InvalidTypeException();
			case JdwpReplyPacket.INVALID_CLASS:
				throw new ClassNotLoadedException(name());
			case JdwpReplyPacket.INVALID_THREAD:
				throw new IncompatibleThreadStateException();
			case JdwpReplyPacket.THREAD_NOT_SUSPENDED:
				throw new IncompatibleThreadStateException();
			case JdwpReplyPacket.NOT_IMPLEMENTED:
				throw new UnsupportedOperationException(JDIMessages.InterfaceTypeImpl_Static_interface_methods_require_newer_JVM);
			}

			defaultReplyErrorHandler(replyPacket.errorCode());
			DataInputStream replyData = replyPacket.dataInStream();
			ValueImpl value = ValueImpl.readWithTag(this, replyData);
			ObjectReferenceImpl exception = ObjectReferenceImpl
					.readObjectRefWithTag(this, replyData);
			if (exception != null)
				throw new InvocationException(exception);
			return value;
		} catch (IOException e) {
			defaultIOExceptionHandler(e);
			return null;
		} finally {
			handledJdwpRequest();
		}
	}

}
