/*
 * Copyright 1998-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.jdi;

import java.util.List;
import java.util.Map;

/**
 * The type of an object in a target VM. ReferenceType encompasses
 * classes, interfaces, and array types as defined in the
 * <a href="http://java.sun.com/docs/books/jls/">
 * Java<sup><font size=-2>TM</font></sup> Language Specification</a>.
 * All ReferenceType objects belong to one of the following
 * subinterfaces:
 * {@link ClassType} for classes,
 * {@link InterfaceType} for interfaces, and
 * {@link ArrayType} for arrays.
 * Note that primitive classes (for example, the
 * {@link ClassObjectReference#reflectedType() reflected type} of
 * {@link java.lang.Integer#TYPE Integer.TYPE})
 * are represented as ClassType.
 * The VM creates Class objects for all three, so from the VM perspective,
 * each ReferenceType maps to a distinct Class object.
 * <p>
 * ReferenceTypes can
 * be obtained by querying a particular {@link ObjectReference} for its
 * type or by getting a list of all reference types from the
 * {@link VirtualMachine}.
 * <p>
 * ReferenceType provides access to static type information such as
 * methods and fields and provides access to dynamic type
 * information such as the corresponding Class object and the classloader.
 * <p>
 * Any method on <code>ReferenceType</code> which directly or
 * indirectly takes <code>ReferenceType</code> as an parameter may throw
 * {@link com.sun.jdi.VMDisconnectedException} if the target VM is
 * disconnected and the {@link com.sun.jdi.event.VMDisconnectEvent} has been or is
 * available to be read from the {@link com.sun.jdi.event.EventQueue}.
 * <p>
 * Any method on <code>ReferenceType</code> which directly or
 * indirectly takes <code>ReferenceType</code> as an parameter may throw
 * {@link com.sun.jdi.VMOutOfMemoryException} if the target VM has run out of memory.
 * <p>
 * Any method on <code>ReferenceType</code> or which directly or indirectly takes
 * <code>ReferenceType</code> as parameter may throw
 * {@link com.sun.jdi.ObjectCollectedException} if the mirrored type has been unloaded.
 *
 * @see ObjectReference
 * @see ObjectReference#referenceType
 * @see VirtualMachine
 * @see VirtualMachine#allClasses
 *
 * @author Robert Field
 * @author Gordon Hirsch
 * @author James McIlree
 * @since  1.3
 */
public interface ReferenceType
    extends Type, Comparable<ReferenceType>, Accessible
{

    /**
     * Gets the fully qualified name of this type. The returned name
     * is formatted as it might appear in a Java programming langauge
     * declaration for objects of this type.
     * <p>
     * For primitive classes
     * the returned name is the name of the corresponding primitive
     * type; for example, "int" is returned as the name of the class
     * represented by {@link java.lang.Integer#TYPE Integer.TYPE}.
     * @return a string containing the type name.
     */
    String name();

    /**
     * Gets the generic signature for this type if there is one.
     * Generic signatures are described in the
     * <a href="http://java.sun.com/docs/books/vmspec">
     * "Java<sup><font size=-2>TM</font></sup>
     * Virtual Machine Specification, 3rd Edition.</a>
     *
     * @return a string containing the generic signature, or <code>null</code>
     * if there is no generic signature.
     *
     * @since 1.5
     */
    String genericSignature();

    /**
     * Gets the classloader object which loaded the class corresponding
     * to this type.
     *
     * @return a {@link ClassLoaderReference} which mirrors the classloader,
     * or <code>null</code> if the class was loaded through the bootstrap class
     * loader.
     */
    ClassLoaderReference classLoader();

    /**
     * Gets an identifying name for the source corresponding to the
     * declaration of this type. Interpretation of this string is
     * the responsibility of the source repository mechanism.
     * <P>
     * The returned name is dependent on VM's default stratum
     * ({@link VirtualMachine#getDefaultStratum()}).
     * In the reference implementation, when using the base stratum,
     * the returned string is the
     * unqualified name of the source file containing the declaration
     * of this type.  In other strata the returned source name is
     * the first source name for that stratum.  Since other languages
     * may have more than one source name for a reference type,
     * the use of {@link Location#sourceName()} or
     * {@link #sourceNames(String)} is preferred.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes,
     * AbsentInformationException is always thrown.
     *
     * @return the string source file name
     * @throws AbsentInformationException if the source name is not
     * known
     */
    String sourceName() throws AbsentInformationException;

    /**
     * Gets the identifying names for all the source corresponding to the
     * declaration of this type. Interpretation of these names is
     * the responsibility of the source repository mechanism.
     * <P>
     * The returned names are for the specified stratum
     * (see {@link Location} for a description of strata).
     * In the reference implementation, when using the Java
     * programming language stratum,
     * the returned List contains one element: a String which is the
     * unqualified name of the source file containing the declaration
     * of this type.  In other strata the returned source names are
     * all the source names defined for that stratum.
     *
     * @param stratum The stratum to retrieve information from
     * or <code>null</code> for the declaring type's
     * default stratum.
     *
     * @return a List of String objects each representing a source name
     *
     * @throws AbsentInformationException if the source names are not
     * known.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes,
     * AbsentInformationException is always thrown.
     *
     * @since 1.4
     */
    List<String> sourceNames(String stratum) throws AbsentInformationException;

    /**
     * Gets the paths to the source corresponding to the
     * declaration of this type. Interpretation of these paths is
     * the responsibility of the source repository mechanism.
     * <P>
     * The returned paths are for the specified stratum
     * (see {@link Location} for a description of strata).
     * In the reference implementation, for strata which
     * do not explicitly specify source path (the Java
     * programming language stratum never does), the returned
     * strings are the {@link #sourceNames(String)} prefixed by
     * the package name of this ReferenceType
     * converted to a platform dependent path.
     * For example, on a Windows platform,
     * <CODE>java.lang.Thread</CODE>
     * would return a List containing one element:
     * <CODE>"java\lang\Thread.java"</CODE>.
     *
     * @param stratum The stratum to retrieve information from
     * or <code>null</code> for the declaring type's
     * default stratum.
     *
     * @return a List of String objects each representing a source path
     *
     * @throws AbsentInformationException if the source names are not
     * known.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes,
     * AbsentInformationException is always thrown.
     *
     * @since 1.4
     */
    List<String> sourcePaths(String stratum) throws AbsentInformationException;

    /**
     * Get the source debug extension of this type.
     * <p>
     * Not all target virtual machines support this operation.
     * Use
     * {@link VirtualMachine#canGetSourceDebugExtension() canGetSourceDebugExtension()}
     * to determine if the operation is supported.
     * @return as a string the source debug extension attribute
     * @throws AbsentInformationException if the extension is not
     * specified
     * @throws java.lang.UnsupportedOperationException if
     * the target virtual machine does not support this
     * operation - see
     * {@link VirtualMachine#canGetSourceDebugExtension() canGetSourceDebugExtension()},
     */
    String sourceDebugExtension() throws AbsentInformationException;

    /**
     * Determines if this type was declared static. Only nested types,
     * can be declared static, so <code>false</code> is returned
     * for any package-level type, array type, or primitive class.
     *
     * @return <code>true</code> if this type is static; false otherwise.
     */
    boolean isStatic();

    /**
     * Determines if this type was declared abstract.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes,
     * the return value is undefined.
     *
     * @return <code>true</code> if this type is abstract; false otherwise.
     */
    boolean isAbstract();

    /**
     * Determines if this type was declared final.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes,
     * the return value is always true.
     *
     * @return <code>true</code> if this type is final; false otherwise.
     */
    boolean isFinal();

    /**
     * Determines if this type has been prepared. See the JVM
     * specification for a definition of class preparation.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes,
     * the return value is undefined.
     *
     * @return <code>true</code> if this type is prepared; false otherwise.
     */
    boolean isPrepared();

    /**
     * Determines if this type has been verified. See the JVM
     * specification for a definition of class verification.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes,
     * the return value is undefined.
     *
     * @return <code>true</code> if this type is verified; false otherwise.
     */
    boolean isVerified();

    /**
     * Determines if this type has been initialized. See the JVM
     * specification for a definition of class verification.
     * For {@link InterfaceType}, this method always returns the
     * same value as {@link #isPrepared()}.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes,
     * the return value is undefined.
     *
     * @return <code>true</code> if this type is initialized; false otherwise.
     */
    boolean isInitialized();

    /**
     * Determines if initialization failed for this class. See the JVM
     * specification for details on class initialization.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes,
     * the return value is undefined.
     *
     * @return <code>true</code> if initialization was attempted and
     * failed; false otherwise.
     */
    boolean failedToInitialize();

    /**
     * Returns a list containing each {@link Field} declared in this type.
     * Inherited fields are not included. Any synthetic fields created
     * by the compiler are included in the list.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes, the returned
     * list is always empty.
     *
     * @return a list {@link Field} objects; the list has length 0
     * if no fields exist.
     * @throws ClassNotPreparedException if this class not yet been
     * prepared.
     */
    List<Field> fields();

    /**
     * Returns a list containing each unhidden and unambiguous {@link Field}
     * in this type.
     * Each field that can be accessed from the class
     * or its instances with its simple name is included. Fields that
     * are ambiguously multiply inherited or fields that are hidden by
     * fields with the same name in a more recently inherited class
     * cannot be accessed
     * by their simple names and are not included in the returned
     * list. All other inherited fields are included.
     * See JLS section 8.3 for details.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes, the returned
     * list is always empty.
     *
     * @return a List of {@link Field} objects; the list has length
     * 0 if no visible fields exist.
     * @throws ClassNotPreparedException if this class not yet been
     * prepared.
     */
    List<Field> visibleFields();

    /**
     * Returns a list containing each {@link Field} declared in this type,
     * and its superclasses, implemented interfaces, and/or superinterfaces.
     * All declared and inherited
     * fields are included, regardless of whether they are hidden or
     * multiply inherited.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes, the returned
     * list is always empty.
     *
     * @return a List of {@link Field} objects; the list has length
     * 0 if no fields exist.
     * @throws ClassNotPreparedException if this class not yet been
     * prepared.
     */
    List<Field> allFields();

    /**
     * Finds the visible {@link Field} with the given
     * non-ambiguous name. This method follows the
     * inheritance rules specified in the JLS (8.3.3) to determine
     * visibility.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes, the returned
     * value is always null.
     *
     * @param fieldName a String containing the name of desired field.
     * @return a {@link Field} object which mirrors the found field, or
     * null if there is no field with the given name or if the given
     * name is ambiguous.
     * @throws ClassNotPreparedException if this class not yet been
     * prepared.
     */
    Field fieldByName(String fieldName);

    /**
     * Returns a list containing each {@link Method} declared
     * directly in this type.
     * Inherited methods are not included. Constructors,
     * the initialization method if any, and any synthetic methods created
     * by the compiler are included in the list.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes, the returned
     * list is always empty.
     *
     * @return a list {@link Method} objects; the list has length 0
     * if no methods exist.
     * @throws ClassNotPreparedException if this class not yet been
     * prepared.
     */
    List<Method> methods();

    /**
     * Returns a list containing each {@link Method}
     * declared or inherited by this type. Methods from superclasses
     * or superinterfaces that that have been hidden or overridden
     * are not included.
     * <p>
     * Note that despite this exclusion, multiple inherited methods
     * with the same signature can be present in the returned list, but
     * at most one can be a member of a {@link ClassType}.
     * See JLS section 8.4.6 for details.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes, the returned
     * list is always empty.
     *
     * @return a List of {@link Method} objects; the list has length
     * 0 if no visible methods exist.
     * @throws ClassNotPreparedException if this class not yet been
     * prepared.
     */
    List<Method> visibleMethods();

    /**
     * Returns a list containing each {@link Method} declared in this type,
     * and its superclasses, implemented interfaces, and/or superinterfaces.
     * All declared and inherited
     * methods are included, regardless of whether they are hidden or
     * overridden.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes, the returned
     * list is always empty.
     *
     * @return a List of {@link Method} objects; the list has length
     * 0 if no methods exist.
     * @throws ClassNotPreparedException if this class not yet been
     * prepared.
     */
    List<Method> allMethods();

    /**
     * Returns a List containing each visible {@link Method} that
     * has the given name.  This is most commonly used to
     * find overloaded methods.
     * <p>
     * Overridden and hidden methods are not included.
     * See JLS (8.4.6) for details.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes, the returned
     * list is always empty.
     *
     * @param name the name of the method to find.
     * @return a List of {@link Method} objects that match the given
     * name; the list has length 0 if no matching methods are found.
     * @throws ClassNotPreparedException if this class not yet been
     * prepared.
     */
    List<Method> methodsByName(String name);

    /**
     * Returns a List containing each visible {@link Method} that
     * has the given name and signature.
     * The signature string is the
     * JNI signature for the target method:
     * <ul>
     * <li><code>()V</code>
     * <li><code>([Ljava/lang/String;)V</code>
     * <li><code>(IIII)Z</code>
     * </ul>
     * This method follows the inheritance rules specified
     * in the JLS (8.4.6) to determine visibility.
     * <p>
     * At most one method in the list is a concrete method and a
     * component of {@link ClassType}; any other methods in the list
     * are abstract. Use {@link ClassType#concreteMethodByName} to
     * retrieve only the matching concrete method.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes, the returned
     * list is always empty.
     *
     * @param name the name of the method to find.
     * @param signature the signature of the method to find
     * @return a List of {@link Method} objects that match the given
     * name and signature; the list has length 0 if no matching methods
     * are found.
     * @throws ClassNotPreparedException if this class not yet been
     * prepared.
     */
    List<Method> methodsByName(String name, String signature);

    /**
     * Returns a List containing {@link ReferenceType} objects that are
     * declared within this type and are currently loaded into the Virtual
     * Machine.  Both static nested types and non-static nested
     * types (that is, inner types) are included. Local inner types
     * (declared within a code block somewhere in this reference type) are
     * also included in the returned list.
     * <p>
     * For arrays ({@link ArrayType}) and primitive classes, the returned
     * list is always empty.
     *
     * @return a List of nested {@link ReferenceType} objects; the list
     * has 0 length if there are no nested types.
     */
    List<ReferenceType> nestedTypes();

    /**
     * Gets the {@link Value} of a given static {@link Field} in this type.
     * The Field must be valid for this type;
     * that is, it must be declared in this type, a superclass, a
     * superinterface, or an implemented interface.
     *
     * @param field the field containing the requested value
     * @return the {@link Value} of the instance field.
     * @throws java.lang.IllegalArgumentException if the field is not valid for
     * this object's class.
     */
    Value getValue(Field field);

    /**
     * Returns a map containing the {@link Value} of each
     * static {@link Field} in the given list.
     * The Fields must be valid for this type;
     * that is, they must be declared in this type, a superclass, a
     * superinterface, or an implemented interface.
     *
     * @param fields a list of {@link Field} objects containing the
     * requested values.
     * @return a Map of the requested {@link Field} objects with
     * their {@link Value}.
     * @throws java.lang.IllegalArgumentException if any field is not valid for
     * this object's class.
     * @throws VMMismatchException if a {@link Mirror} argument and this mirror
     * do not belong to the same {@link VirtualMachine}.
     */
    Map<Field,Value> getValues(List<? extends Field> fields);

    /**
     * Returns the class object that corresponds to this type in the
     * target VM. The VM creates class objects for every kind of
     * ReferenceType: classes, interfaces, and array types.
     * @return the {@link ClassObjectReference} for this reference type
     * in the target VM.
     */
    ClassObjectReference classObject();

    /**
     * Returns a list containing a {@link Location} object
     * for each executable source line in this reference type.
     * <P>
     * This method is equivalent to
     * <code>allLineLocations(vm.getDefaultStratum(),null)</code> -
     * see {@link #allLineLocations(String,String)}
     * for more information.
     *
     * @throws AbsentInformationException if there is no line
     * number information for this class and there are non-native,
     * non-abstract executable members of this class.
     *
     * @throws ClassNotPreparedException if this class not yet
     * been prepared.
     */
    List<Location> allLineLocations() throws AbsentInformationException;

    /**
     * Returns a list containing a {@link Location} object
     * for each executable source line in this reference type.
     * Each location maps a source line to a range of code
     * indices.
     * The beginning of the range can be determined through
     * {@link Location#codeIndex}.  The returned list may contain
     * multiple locations for a particular line number, if the
     * compiler and/or VM has mapped that line to two or more
     * disjoint code index ranges.  Note that it is possible for
     * the same source line to represent different code index
     * ranges in <i>different</i> methods.
     * <P>
     * For arrays ({@link ArrayType}) and primitive classes, the
     * returned list is always empty.  For interfaces ({@link
     * InterfaceType}), the returned list will be non-empty only
     * if the interface has executable code in its class
     * initialization.
     * <P>
     * Returned list is for the specified <i>stratum</i>
     * (see {@link Location} for a description of strata).
     *
     * @param stratum The stratum to retrieve information from
     * or <code>null</code> for the {@link #defaultStratum()}.
     *
     * @param sourceName Return locations only within this
     * source file or <code>null</code> to return locations.
     *
     * @return a List of all source line {@link Location} objects.
     *
     * @throws AbsentInformationException if there is no line
     * number information for this class and there are non-native,
     * non-abstract executable members of this class.
     * Or if <i>sourceName</i> is non-<code>null</code>
     * and source name information is not present.
     *
     * @throws ClassNotPreparedException if this class not yet
     * been prepared.
     *
     * @since 1.4
     */
    List<Location> allLineLocations(String stratum, String sourceName)
                             throws AbsentInformationException;

    /**
     * Returns a List containing all {@link Location} objects
     * that map to the given line number.
     * <P>
     * This method is equivalent to
     * <code>locationsOfLine(vm.getDefaultStratum(), null,
     * lineNumber)</code> -
     * see {@link
     * #locationsOfLine(java.lang.String,java.lang.String,int)}
     * for more information.
     *
     * @param lineNumber the line number
     *
     * @return a List of all {@link Location} objects that map to
     * the given line.
     *
     * @throws AbsentInformationException if there is no line
     * number information for this class.
     *
     * @throws ClassNotPreparedException if this class not yet
     * been prepared.
     *
     * @see VirtualMachine#getDefaultStratum()
     */
    List<Location> locationsOfLine(int lineNumber)
        throws AbsentInformationException;

    /**
     * Returns a List containing all {@link Location} objects
     * that map to the given line number.
     * <P>
     * For arrays ({@link ArrayType}) and primitive classes, the
     * returned list is always empty.
     * For interfaces ({@link InterfaceType}), the returned list
     * will be non-empty only if the interface has executable code
     * in its class initialization at the specified line number.
     * An empty list will be returned if there is no executable
     * code at the specified line number.
     * <p>
     * Returned list is for the specified <i>stratum</i>
     * (see {@link Location} for a description of strata).
     *
     * @param stratum the stratum to use for comparing line number
     *                and source name, or <code>null</code> to
     *                use the {@link #defaultStratum()}.
     *
     * @param sourceName the source name containing the line
     *                   number, or <code>null</code> to match
     *                   all source names
     *
     * @param lineNumber the line number
     *
     * @return a List of all {@link Location} objects that map
     *         to the given line.
     *
     * @throws AbsentInformationException if there is no line
     *         number information for this class.
     *         Or if <i>sourceName</i> is non-<code>null</code>
     *         and source name information is not present.
     *
     * @throws ClassNotPreparedException if this class not yet
     *         been prepared.
     *
     * @since 1.4
     */
    List<Location> locationsOfLine(String stratum,
                                   String sourceName,
                                   int lineNumber)
                     throws AbsentInformationException;

    /**
     * Return the available strata for this reference type.
     * <P>
     * See the {@link Location} for a description of strata.
     *
     * @return List of <CODE>java.lang.String</CODE>, each
     * representing a stratum
     *
     * @since 1.4
     */
    List<String> availableStrata();

    /**
     * Returns the default stratum for this reference type.
     * This value is specified in the class file and cannot
     * be set by the user.  If the class file does not
     * specify a default stratum the base stratum
     * (<code>"Java"</code>) will be returned.
     * <P>
     * See the {@link Location} for a description of strata.
     *
     * @since 1.4
     */
    String defaultStratum();

    /**
     * Returns instances of this ReferenceType.
     * Only instances that are reachable for the purposes of garbage collection
     * are returned.
     * <p>
     * Not all target virtual machines support this operation.
     * Use {@link VirtualMachine#canGetInstanceInfo()}
     * to determine if the operation is supported.
     *
     * @see VirtualMachine#instanceCounts(List)
     * @see ObjectReference#referringObjects(long)
     *
     * @param maxInstances the maximum number of instances to return.
     *        Must be non-negative.  If zero, all instances are returned.
     * @return a List of {@link ObjectReference} objects.  If there are
     * no instances of this ReferenceType, a zero-length list is returned.
     *
     * @throws java.lang.UnsupportedOperationException if
     * the target virtual machine does not support this
     * operation - see
     * {@link VirtualMachine#canGetInstanceInfo() canGetInstanceInfo()}
     * @throws java.lang.IllegalArgumentException if maxInstances is less
     *         than zero.
     * @since 1.6
     */
    List<ObjectReference> instances(long maxInstances);

    /**
     * Compares the specified Object with this ReferenceType for equality.
     *
     * @return  true if the Object is a {@link ReferenceType}, if the
     * ReferenceTypes belong to the same VM, and if they mirror classes
     * which correspond to the same instance of java.lang.Class in that VM.
     */
    boolean equals(Object obj);

    /**
     * Returns the hash code value for this ObjectReference.
     *
     * @return the integer hash code
     */
    int hashCode();

    /**
     * Returns the class major version number, as defined in the class file format
     * of the Java Virtual Machine Specification.
     *
     * For arrays ({@link ArrayType}) and primitive classes,
     * the returned major version number value is zero.
     *
     * Not all target virtual machines support this operation.
     * Use {@link VirtualMachine#canGetClassFileVersion()}
     * to determine if the operation is supported.
     *
     * @return the major version number of the class.
     *
     * @throws java.lang.UnsupportedOperationException if
     * the target virtual machine does not support this
     * operation - see
     * {@link VirtualMachine#canGetClassFileVersion() canGetClassFileVersion()}
     *
     * @since 1.6
     */
    int majorVersion();


    /**
     * Returns the class minor version number, as defined in the class file format
     * of the Java Virtual Machine Specification.
     *
     * For arrays ({@link ArrayType}) and primitive classes,
     * the returned minor version number value is zero.
     *
     * Not all target virtual machines support this operation.
     * Use {@link VirtualMachine#canGetClassFileVersion()}
     * to determine if the operation is supported.
     *
     * @return the minor version number of the class.
     *
     * @throws java.lang.UnsupportedOperationException if
     * the target virtual machine does not support this
     * operation - see
     * {@link VirtualMachine#canGetClassFileVersion() canGetClassFileVersion()}
     *
     * @since 1.6
     */
    int minorVersion();

    /**
     * Returns the number of entries in the constant pool plus one.
     * This corresponds to the constant_pool_count item of the Class File Format
     * in the Java Virtual Machine Specification.
     *
     * For arrays ({@link ArrayType}) and primitive classes,
     * the returned constant pool count value is zero.
     *
     * Not all target virtual machines support this operation.
     * Use {@link VirtualMachine#canGetConstantPool()}
     * to determine if the operation is supported.
     *
     * @return total number of constant pool entries for a class plus one.
     *
     * @throws java.lang.UnsupportedOperationException if
     * the target virtual machine does not support this
     * operation - see
     * {@link VirtualMachine#canGetConstantPool() canGetConstantPool()}
     *
     * @see #constantPool()
     * @since 1.6
     */
    int constantPoolCount();

    /**
     * Returns the raw bytes of the constant pool in the format of the
     * constant_pool item of the Class File Format in the Java Virtual
     * Machine Specification. The format of the constant pool may
     * differ between versions of the Class File Format, so, the
     * minor and major class version numbers should be checked for
     * compatibility.
     *
     * For arrays ({@link ArrayType}) and primitive classes,
     * a zero length byte array is returned.
     *
     * Not all target virtual machines support this operation.
     * Use {@link VirtualMachine#canGetConstantPool()}
     * to determine if the operation is supported.
     *
     * @return the raw bytes of constant pool.
     *
     * @throws java.lang.UnsupportedOperationException if
     * the target virtual machine does not support this
     * operation - see
     * {@link VirtualMachine#canGetConstantPool() canGetConstantPool()}
     *
     * @see #constantPoolCount()
     * @since 1.6
     */
     byte[] constantPool();

}
