/*******************************************************************************
 * 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.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 Map<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) {
			// 509259 use temporary variable to workaround fMethodTable lazy initialization race
			Map<JdwpMethodID, Method> methodTable = new HashMap<>();
			Iterator<Method> iter = methods().iterator();
			while (iter.hasNext()) {
				MethodImpl method = (MethodImpl) iter.next();
				methodTable.put(method.getMethodID(), method);
			}
			fMethodTable = Collections.unmodifiableMap(methodTable);
		}
		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();
		}
	}

}
