/* 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Copyright (C) 2006-2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package java.lang;

import dalvik.system.VMStack;

import org.apache.harmony.kernel.vm.StringUtils;
import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
import org.apache.harmony.luni.lang.reflect.Types;

import java.io.InputStream;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.ref.SoftReference;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Collection;
import java.util.HashMap;
import java.net.URL;
import java.security.ProtectionDomain;

import static java.lang.ClassCache.REFLECT;
import static java.lang.ClassCache.compareClassLists;
import static java.lang.ClassCache.findMethodByName;
import static java.lang.ClassCache.findFieldByName;

/**
 * The in-memory representation of a Java class. This representation serves as
 * the starting point for querying class-related information, a process usually
 * called "reflection". There are basically three types of {@code Class}
 * instances: those representing real classes and interfaces, those representing
 * primitive types, and those representing array classes.
 * 
 * <h4>Class instances representing object types (classes or interfaces)</h4>
 * <p>
 * These represent an ordinary class or interface as found in the class
 * hierarchy. The name associated with these {@code Class} instances is simply
 * the fully qualified class name of the class or interface that it represents.
 * In addition to this human-readable name, each class is also associated by a
 * so-called <em>signature</em>, which is the letter "L", followed by the
 * class name and a semicolon (";"). The signature is what the runtime system
 * uses internally for identifying the class (for example in a DEX file).
 * </p>
 * <h4>Classes representing primitive types</h4>
 * <p>
 * These represent the standard Java primitive types and hence share their
 * names (for example "int" for the {@code int} primitive type). Although it is
 * not possible to create new instances based on these {@code Class} instances,
 * they are still useful for providing reflection information, and as the
 * component type of array classes. There is one {@code Class} instance for each
 * primitive type, and their signatures are:
 * </p>
 * <ul>
 * <li>{@code B} representing the {@code byte} primitive type</li>
 * <li>{@code S} representing the {@code short} primitive type</li>
 * <li>{@code I} representing the {@code int} primitive type</li>
 * <li>{@code J} representing the {@code long} primitive type</li>
 * <li>{@code F} representing the {@code float} primitive type</li>
 * <li>{@code D} representing the {@code double} primitive type</li>
 * <li>{@code C} representing the {@code char} primitive type</li>
 * <li>{@code Z} representing the {@code boolean} primitive type</li>
 * <li>{@code V} representing void function return values</li>
 * </ul>
 * <p>
 * <h4>Classes representing array classes</h4>
 * <p>
 * These represent the classes of Java arrays. There is one such {@code Class}
 * instance per combination of array leaf component type and arity (number of
 * dimensions). In this case, the name associated with the {@code Class}
 * consists of one or more left square brackets (one per dimension in the array)
 * followed by the signature of the class representing the leaf component type,
 * which can be either an object type or a primitive type. The signature of a
 * {@code Class} representing an array type is the same as its name. Examples
 * of array class signatures are:
 * </p>
 * <ul>
 * <li>{@code [I} representing the {@code int[]} type</li>
 * <li>{@code [Ljava/lang/String;} representing the {@code String[]} type</li>
 * <li>{@code [[[C} representing the {@code char[][][]} type (three dimensions!)</li>
 * </ul>
 */
public final class Class<T> implements Serializable, AnnotatedElement, GenericDeclaration, Type {

    private static final long serialVersionUID = 3206093459760846163L;

    /**
     * This field is initialized by dalvikvm when the class is loaded.
     */
    private transient ProtectionDomain pd;

    /**
     * null-ok; cache of reflective information, wrapped in a soft
     * reference
     */
    private transient volatile SoftReference<ClassCache<T>> cacheRef;
    
    private Class() {
        // Prevent this class to be instantiated, instance
        // should be created by JVM only
    }

    /**
     * Get the Signature attribute for this class.  Returns null if not found.
     */
    private String getSignatureAttribute() {
        Object[] annotation = getSignatureAnnotation();

        if (annotation == null) {
            return null;
        }

        return StringUtils.combineStrings(annotation);
    }

    /**
     * Get the Signature annotation for this class.  Returns null if not found.
     */
    native private Object[] getSignatureAnnotation();

    /**
     * Returns a {@code Class} object which represents the class with the
     * specified name. The name should be the name of a class as described in
     * the {@link Class class definition}; however, {@code Class}es representing
     * primitive types can not be found using this method.
     * <p>
     * If the class has not been loaded so far, it is being loaded and linked
     * first. This is done through either the class loader of the calling class
     * or one of its parent class loaders. The class is also being initialized,
     * which means that a possible static initializer block is executed.  
     * 
     * @param className
     *            the name of the non-primitive-type class to find.
     * @return the named {@code Class} instance.
     * @throws ClassNotFoundException
     *             if the requested class can not be found.
     * @throws LinkageError
     *             if an error occurs during linkage
     * @throws ExceptionInInitializerError
     *             if an exception occurs during static initialization of a
     *             class.
     */
    public static Class<?> forName(String className) throws ClassNotFoundException {
        return forName(className, true, VMStack.getCallingClassLoader());
    }

    /**
     * Returns a {@code Class} object which represents the class with the
     * specified name. The name should be the name of a class as described in
     * the {@link Class class definition}, however {@code Class}es representing
     * primitive types can not be found using this method. Security rules will
     * be obeyed.
     * <p>
     * If the class has not been loaded so far, it is being loaded and linked
     * first. This is done through either the specified class loader or one of
     * its parent class loaders. The caller can also request the class to be
     * initialized, which means that a possible static initializer block is
     * executed.  
     * 
     * @param className
     *            the name of the non-primitive-type class to find.
     * @param initializeBoolean
     *            indicates whether the class should be initialized.
     * @param classLoader
     *            the class loader to use to load the class.
     * @return the named {@code Class} instance.
     * @throws ClassNotFoundException
     *             if the requested class can not be found.
     * @throws LinkageError
     *             if an error occurs during linkage
     * @throws ExceptionInInitializerError
     *             if an exception occurs during static initialization of a
     *             class.
     */
    public static Class<?> forName(String className, boolean initializeBoolean,
            ClassLoader classLoader) throws ClassNotFoundException {
        
        if (classLoader == null) {
            SecurityManager smgr = System.getSecurityManager();
            if (smgr != null) {
                ClassLoader calling = VMStack.getCallingClassLoader();
                if (calling != null) {
                    smgr.checkPermission(new RuntimePermission("getClassLoader"));
                }
            }
            
            classLoader = ClassLoader.getSystemClassLoader();
        }
        // Catch an Exception thrown by the underlying native code. It wraps
        // up everything inside a ClassNotFoundException, even if e.g. an
        // Error occurred during initialization. This as a workaround for
        // an ExceptionInInitilaizerError that's also wrapped. It is actually
        // expected to be thrown. Maybe the same goes for other errors.
        // Not wrapping up all the errors will break android though.
        Class<?> result;
        try {
            result = classForName(className, initializeBoolean,
                    classLoader);
        } catch (ClassNotFoundException e) {
            Throwable cause = e.getCause(); 
            if (cause instanceof ExceptionInInitializerError) {
                throw (ExceptionInInitializerError) cause;
            }
            throw e;
        }
        return result;
    }

    /*
     * Returns a class by name without any security checks.
     *
     * @param className The name of the non-primitive type class to find
     * @param initializeBoolean A boolean indicating whether the class should be
     *        initialized
     * @param classLoader The class loader to use to load the class
     * @return the named class.
     * @throws ClassNotFoundException If the class could not be found
     */
    static native Class<?> classForName(String className, boolean initializeBoolean,
            ClassLoader classLoader) throws ClassNotFoundException;
    
    /**
     * Returns an array containing {@code Class} objects for all public classes
     * and interfaces that are members of this class. This includes public
     * members inherited from super classes and interfaces. If there are no such
     * class members or if this object represents a primitive type then an array
     * of length 0 is returned.
     * 
     * @return the public class members of the class represented by this object.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     */
    public Class[] getClasses() {
        // BEGIN android-note
        // trying to get closer to the RI which returns a raw class array.
        // copied from newer version of harmony
        // END android-note
        checkPublicMemberAccess();
        return getFullListOfClasses(true);
    }

    /**
     * Returns the annotation of the given type. If there is no such annotation
     * then the method returns {@code null}.
     * 
     * @param annotationClass
     *            the annotation type.
     * @return the annotation of the given type, or {@code null} if there is no
     *         such annotation.
     */
    @SuppressWarnings("unchecked")
    public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
        Annotation[] list = getAnnotations();
        for (int i = 0; i < list.length; i++) {
            if (annotationClass.isInstance(list[i])) {
                return (A)list[i];
            }
        }
        
        return null;
    }

    /**
     * Returns all the annotations of this class. If there are no annotations
     * then an empty array is returned.
     * 
     * @return a copy of the array containing this class' annotations.
     * @see #getDeclaredAnnotations()         
     */
    public Annotation[] getAnnotations() {
        /*
         * We need to get the annotations declared on this class, plus the
         * annotations from superclasses that have the "@Inherited" annotation
         * set.  We create a temporary map to use while we accumulate the
         * annotations and convert it to an array at the end.
         *
         * It's possible to have duplicates when annotations are inherited.
         * We use a Map to filter those out.
         *
         * HashMap might be overkill here.
         */
        HashMap<Class, Annotation> map = new HashMap<Class, Annotation>();
        Annotation[] annos = getDeclaredAnnotations();

        for (int i = annos.length-1; i >= 0; --i)
            map.put(annos[i].annotationType(), annos[i]);

        for (Class sup = getSuperclass(); sup != null;
                sup = sup.getSuperclass()) {
            annos = sup.getDeclaredAnnotations();
            for (int i = annos.length-1; i >= 0; --i) {
                Class clazz = annos[i].annotationType();
                if (!map.containsKey(clazz) &&
                        clazz.isAnnotationPresent(Inherited.class)) {
                    map.put(clazz, annos[i]);
                }
            }
        }

        /* convert annotation values from HashMap to array */
        Collection<Annotation> coll = map.values();
        return coll.toArray(new Annotation[coll.size()]);
    }

    /**
     * Returns the canonical name of this class. If this class does not have a
     * canonical name as defined in the Java Language Specification, then the
     * method returns {@code null}.
     * 
     * @return this class' canonical name, or {@code null} if it does not have a
     *         canonical name.
     */
    public String getCanonicalName() {
        if (isLocalClass() || isAnonymousClass())
            return null;

        if (isArray()) {
            /*
             * The canonical name of an array type depends on the (existence of)
             * the component type's canonical name. 
             */
            String name = getComponentType().getCanonicalName();
            if (name != null) {
                return name + "[]";
            } 
        } else if (isMemberClass()) {
            /*
             * The canonical name of an inner class depends on the (existence
             * of) the declaring class' canonical name. 
             */
            String name = getDeclaringClass().getCanonicalName();
            if (name != null) {
                return name + "." + getSimpleName();
            }
        } else {
            /*
             * The canonical name of a top-level class or primitive type is
             * equal to the fully qualified name. 
             */
            return getName();
        }
        
        /*
         * Other classes don't have a canonical name.
         */
        return null;
    }

    /**
     * Returns the class loader which was used to load the class represented by
     * this {@code Class}. Implementations are free to return {@code null} for
     * classes that were loaded by the bootstrap class loader. The Android
     * reference implementation, though, returns a reference to an actual
     * representation of the bootstrap class loader.
     * 
     * @return the class loader for the represented class.
     * @throws SecurityException
     *             if a security manager exists and it does not allow accessing
     *             the class loader.
     * @see ClassLoader
     */
    public ClassLoader getClassLoader() {
        SecurityManager smgr = System.getSecurityManager();
        ClassLoader loader = getClassLoaderImpl();
        if (smgr != null && loader != null) {
            ClassLoader calling = VMStack.getCallingClassLoader();

            if (calling != null && !calling.isAncestorOf(loader)) {
                smgr.checkPermission(new RuntimePermission("getClassLoader"));
            }
        }
        
        if (this.isPrimitive()) {
            return null;
        }
        
        if (loader == null) {
            loader = BootClassLoader.getInstance();
        }
        
        return loader;
    }

    /**
     * This must be provided by the VM vendor, as it is used by other provided
     * class implementations in this package. Outside of this class, it is used
     * by SecurityManager.checkMemberAccess(), classLoaderDepth(),
     * currentClassLoader() and currentLoadedClass(). Return the ClassLoader for
     * this Class without doing any security checks. The bootstrap ClassLoader
     * is returned, unlike getClassLoader() which returns null in place of the
     * bootstrap ClassLoader.
     * 
     * @return the ClassLoader
     * @see ClassLoader#isSystemClassLoader()
     */
    ClassLoader getClassLoaderImpl() {
        ClassLoader loader = getClassLoader(this);
        return loader == null ? BootClassLoader.getInstance() : loader;
    }

    /*
     * Returns the defining class loader for the given class.
     * 
     * @param clazz the class the class loader of which we want
     * @return the class loader
     */
    private static native ClassLoader getClassLoader(Class<?> clazz);
    
    /**
     * Returns a {@code Class} object which represents the component type if
     * this class represents an array type. Returns {@code null} if this class
     * does not represent an array type. The component type of an array type is
     * the type of the elements of the array.
     * 
     * @return the component type of this class.
     */
    public native Class<?> getComponentType();

    /**
     * Returns a {@code Constructor} object which represents the public
     * constructor matching the specified parameter types.
     * 
     * @param parameterTypes
     *            the parameter types of the requested constructor.
     *            {@code (Class[]) null} is equivalent to the empty array.
     * @return the constructor described by {@code parameterTypes}.
     * @throws NoSuchMethodException
     *             if the constructor can not be found.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     * @see #getDeclaredConstructor(Class...)
     */
    @SuppressWarnings("unchecked")
    public Constructor<T> getConstructor(Class... parameterTypes) throws NoSuchMethodException,
            SecurityException {
        checkPublicMemberAccess();
        return getMatchingConstructor(getDeclaredConstructors(this, true), parameterTypes);
    }

    /**
     * Returns an array containing {@code Constructor} objects for all public
     * constructors for the class represented by this {@code Class}. If there
     * are no public constructors or if this {@code Class} represents an array
     * class, a primitive type or void then an empty array is returned.
     * 
     * @return an array with the public constructors of the class represented by
     *         this {@code Class}.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     * @see #getDeclaredConstructors()
     */
    public Constructor[] getConstructors() throws SecurityException {
        // BEGIN android-note
        // trying to get closer to the RI which returns a raw constructor array.
        // copied from newer version of harmony
        // END android-note
        checkPublicMemberAccess();
        return getDeclaredConstructors(this, true);
    }

    /**
     * Returns the annotations that are directly defined on the class
     * represented by this {@code Class}. Annotations that are inherited are not
     * included in the result. If there are no annotations at all, an empty
     * array is returned.
     * 
     * @return a copy of the array containing the annotations defined for the
     *         class that this {@code Class} represents.
     * @see #getAnnotations()
     */
    native public Annotation[] getDeclaredAnnotations();

    /**
     * Returns an array containing {@code Class} objects for all classes and
     * interfaces that are declared as members of the class which this {@code
     * Class} represents. If there are no classes or interfaces declared or if
     * this class represents an array class, a primitive type or void, then an
     * empty array is returned.
     * 
     * @return an array with {@code Class} objects for all the classes and
     *         interfaces that are used in member declarations.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     */
    public Class[] getDeclaredClasses() throws SecurityException {
        // BEGIN android-note
        // trying to get closer to the RI which returns a raw class array.
        // copied from newer version of harmony
        // END android-note
        checkDeclaredMemberAccess();
        return getDeclaredClasses(this, false);
    }

    /*
     * Returns the list of member classes without performing any security checks
     * first. This includes the member classes inherited from superclasses. If no
     * member classes exist at all, an empty array is returned.
     * 
     * @param publicOnly reflects whether we want only public members or all of them
     * @return the list of classes
     */
    private Class<?>[] getFullListOfClasses(boolean publicOnly) {
        Class<?>[] result = getDeclaredClasses(this, publicOnly);
        
        // Traverse all superclasses
        Class<?> clazz = this.getSuperclass();
        while (clazz != null) {
            Class<?>[] temp = getDeclaredClasses(clazz, publicOnly);
            if (temp.length != 0) {
                result = arraycopy(new Class[result.length + temp.length], result, temp);
            }
            
            clazz = clazz.getSuperclass();
        }
        
        return result;
    }

    /*
     * Returns the list of member classes of the given class. No security checks
     * are performed. If no members exist, an empty array is returned.
     * 
     * @param clazz the class the members of which we want
     * @param publicOnly reflects whether we want only public member or all of them
     * @return the class' class members
     */
    native private static Class<?>[] getDeclaredClasses(Class<?> clazz,
        boolean publicOnly);
    
    /**
     * Returns a {@code Constructor} object which represents the constructor
     * matching the specified parameter types that is declared by the class
     * represented by this {@code Class}.
     * 
     * @param parameterTypes
     *            the parameter types of the requested constructor.
     *            {@code (Class[]) null} is equivalent to the empty array.
     * @return the constructor described by {@code parameterTypes}.
     * @throws NoSuchMethodException
     *             if the requested constructor can not be found.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     * @see #getConstructor(Class...)
     */
    @SuppressWarnings("unchecked")
    public Constructor<T> getDeclaredConstructor(Class... parameterTypes)
            throws NoSuchMethodException, SecurityException {
        checkDeclaredMemberAccess();
        return getMatchingConstructor(getDeclaredConstructors(this, false), parameterTypes);
    }

    /**
     * Returns an array containing {@code Constructor} objects for all
     * constructors declared in the class represented by this {@code Class}. If
     * there are no constructors or if this {@code Class} represents an array
     * class, a primitive type or void then an empty array is returned.
     * 
     * @return an array with the constructors declared in the class represented
     *         by this {@code Class}.
     * 
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     * @see #getConstructors()
     */
    public Constructor[] getDeclaredConstructors() throws SecurityException {
        // BEGIN android-note
        // trying to get closer to the RI which returns a raw constructor array.
        // copied from newer version of harmony
        // END android-note
        checkDeclaredMemberAccess();
        return getDeclaredConstructors(this, false);
    }

    /*
     * Returns the list of constructors without performing any security checks
     * first. If no constructors exist, an empty array is returned.
     *
     * @param clazz the class of interest
     * @param publicOnly reflects whether we want only public constructors or all of them
     * @return the list of constructors
     */
    private static native <T> Constructor<T>[] getDeclaredConstructors(Class<T> clazz, boolean publicOnly);

    /*
     * Finds a constructor with a given signature.
     * 
     * @param list the list of constructors to search through
     * @param parameterTypes the formal parameter list
     * @return the matching constructor
     * @throws NoSuchMethodException if the constructor does not exist.
     */
    private Constructor<T> getMatchingConstructor(
            Constructor<T>[] list, Class<?>[] parameterTypes)
            throws NoSuchMethodException {
        for (int i = 0; i < list.length; i++) {
            if (compareClassLists(list[i].getParameterTypes(), parameterTypes)) {
                return list[i];
            }
        }
        
        // BEGIN android-changed
        StringBuilder sb = new StringBuilder();
        sb.append(getSimpleName());
        sb.append('(');
        boolean first = true;
        if (parameterTypes != null) {
            for (Class<?> p : parameterTypes) {
                if (!first) {
                    sb.append(',');
                }
                first = false;
                sb.append(p.getSimpleName());
            }
        }
        sb.append(')');
        throw new NoSuchMethodException(sb.toString());
        // END android-changed
    }
    
    /**
     * Returns a {@code Field} object for the field with the specified name
     * which is declared in the class represented by this {@code Class}.
     * 
     * @param name
     *            the name of the requested field.
     * @return the requested field in the class represented by this class.
     * @throws NoSuchFieldException
     *             if the requested field can not be found.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     * @see #getField(String)
     */
    public Field getDeclaredField(String name)
            throws NoSuchFieldException, SecurityException {
        checkDeclaredMemberAccess();

        Field[] fields = getClassCache().getDeclaredFields();
        Field field = findFieldByName(fields, name);

        /*
         * Make a copy of the private (to the package) object, so that
         * setAccessible() won't alter the private instance.
         */
        return REFLECT.clone(field);
    }

    /**
     * Returns an array containing {@code Field} objects for all fields declared
     * in the class represented by this {@code Class}. If there are no fields or
     * if this {@code Class} represents an array class, a primitive type or void
     * then an empty array is returned.
     * 
     * @return an array with the fields declared in the class represented by
     *         this class.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     * @see #getFields()
     */
    public Field[] getDeclaredFields() throws SecurityException {
        checkDeclaredMemberAccess();

        // Return a copy of the private (to the package) array.
        Field[] fields = getClassCache().getDeclaredFields();
        return ClassCache.deepCopy(fields);
    }
    
    /*
     * Returns the list of fields without performing any security checks
     * first. If no fields exist at all, an empty array is returned.
     * 
     * @param clazz the class of interest
     * @param publicOnly reflects whether we want only public fields or all of them
     * @return the list of fields 
     */
    static native Field[] getDeclaredFields(Class<?> clazz, boolean publicOnly);

    /**
     * Returns a {@code Method} object which represents the method matching the
     * specified name and parameter types that is declared by the class
     * represented by this {@code Class}.
     * 
     * @param name
     *            the requested method's name.
     * @param parameterTypes
     *            the parameter types of the requested method.
     *            {@code (Class[]) null} is equivalent to the empty array.
     * @return the method described by {@code name} and {@code parameterTypes}.
     * @throws NoSuchMethodException
     *             if the requested constructor can not be found.
     * @throws NullPointerException
     *             if {@code name} is {@code null}.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     * @see #getMethod(String, Class...)
     */
    public Method getDeclaredMethod(String name, Class... parameterTypes)
            throws NoSuchMethodException, SecurityException {
        checkDeclaredMemberAccess();

        Method[] methods = getClassCache().getDeclaredMethods();
        Method method = findMethodByName(methods, name, parameterTypes);

        /*
         * Make a copy of the private (to the package) object, so that
         * setAccessible() won't alter the private instance.
         */
        return REFLECT.clone(method);
    }
    
    /**
     * Returns an array containing {@code Method} objects for all methods
     * declared in the class represented by this {@code Class}. If there are no
     * methods or if this {@code Class} represents an array class, a primitive
     * type or void then an empty array is returned.
     * 
     * @return an array with the methods declared in the class represented by
     *         this {@code Class}.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     * @see #getMethods()
     */
    public Method[] getDeclaredMethods() throws SecurityException {
        checkDeclaredMemberAccess();

        // Return a copy of the private (to the package) array.
        Method[] methods = getClassCache().getDeclaredMethods();
        return ClassCache.deepCopy(methods);
    }
    
    /**
     * Returns the list of methods without performing any security checks
     * first. If no methods exist, an empty array is returned.
     */
    static native Method[] getDeclaredMethods(Class<?> clazz, boolean publicOnly);

    /**
     * Gets the {@link ClassCache} for this instance.
     *
     * @return non-null; the cache object
     */
    /*package*/ ClassCache<T> getClassCache() {
        /*
         * Note: It is innocuous if two threads try to simultaneously
         * create the cache, so we don't bother protecting against that.
         */
        ClassCache<T> cache = null;

        if (cacheRef != null) {
            cache = cacheRef.get();
        }

        if (cache == null) {
            cache = new ClassCache<T>(this);
            cacheRef = new SoftReference<ClassCache<T>>(cache);
        }

        return cache;
    }

    /**
     * Returns the declaring {@code Class} of this {@code Class}. Returns
     * {@code null} if the class is not a member of another class or if this
     * {@code Class} represents an array class, a primitive type or void.
     * 
     * @return the declaring {@code Class} or {@code null}.
     */
    native public Class<?> getDeclaringClass();

    /**
     * Returns the enclosing {@code Class} of this {@code Class}. If there is no
     * enclosing class the method returns {@code null}.
     * 
     * @return the enclosing {@code Class} or {@code null}.
     */
    native public Class<?> getEnclosingClass();

    /**
     * Gets the enclosing {@code Constructor} of this {@code Class}, if it is an
     * anonymous or local/automatic class; otherwise {@code null}.
     * 
     * @return the enclosing {@code Constructor} instance or {@code null}.
     */
    native public Constructor<?> getEnclosingConstructor();

    /**
     * Gets the enclosing {@code Method} of this {@code Class}, if it is an
     * anonymous or local/automatic class; otherwise {@code null}.
     * 
     * @return the enclosing {@code Method} instance or {@code null}.
     */
    native public Method getEnclosingMethod();

    /**
     * Gets the {@code enum} constants associated with this {@code Class}.
     * Returns {@code null} if this {@code Class} does not represent an {@code
     * enum} type.
     * 
     * @return an array with the {@code enum} constants or {@code null}.
     */
    @SuppressWarnings("unchecked")
    public T[] getEnumConstants() {
        if (isEnum()) {
            checkPublicMemberAccess();
            T[] values = getClassCache().getEnumValuesInOrder();

            // Copy the private (to the package) array.
            return (T[]) values.clone();
        }
        
        return null;
    }
        
    /**
     * Returns a {@code Field} object which represents the public field with the
     * specified name. This method first searches the class C represented by
     * this {@code Class}, then the interfaces implemented by C and finally the
     * superclasses of C.
     * 
     * @param name
     *            the name of the requested field.
     * @return the public field specified by {@code name}.
     * @throws NoSuchFieldException
     *             if the field can not be found.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     * @see #getDeclaredField(String)
     */
    public Field getField(String name) throws NoSuchFieldException, SecurityException {
        checkPublicMemberAccess();

        Field[] fields = getClassCache().getAllPublicFields();
        Field field = findFieldByName(fields, name);

        /*
         * Make a copy of the private (to the package) object, so that
         * setAccessible() won't alter the private instance.
         */
        return REFLECT.clone(field);
    }

    /**
     * Returns an array containing {@code Field} objects for all public fields
     * for the class C represented by this {@code Class}. Fields may be declared
     * in C, the interfaces it implements or in the superclasses of C. The
     * elements in the returned array are in no particular order.
     * <p>
     * If there are no public fields or if this class represents an array class,
     * a primitive type or {@code void} then an empty array is returned.
     * </p>
     * 
     * @return an array with the public fields of the class represented by this
     *         {@code Class}.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     * @see #getDeclaredFields()
     */
    public Field[] getFields() throws SecurityException {
        checkPublicMemberAccess();

        // Return a copy of the private (to the package) array.
        Field[] fields = getClassCache().getAllPublicFields();
        return ClassCache.deepCopy(fields);
    }

    /**
     * Gets the {@link Type}s of the interfaces that this {@code Class} directly
     * implements. If the {@code Class} represents a primitive type or {@code
     * void} then an empty array is returned.
     * 
     * @return an array of {@link Type} instances directly implemented by the
     *         class represented by this {@code class}.
     */
    public Type[] getGenericInterfaces() {
        GenericSignatureParser parser = new GenericSignatureParser(
                VMStack.getCallingClassLoader2());
        parser.parseForClass(this, getSignatureAttribute());
        return Types.getClonedTypeArray(parser.interfaceTypes);
    }
    
    /**
     * Gets the {@code Type} that represents the superclass of this {@code
     * class}.
     * 
     * @return an instance of {@code Type} representing the superclass.
     */
    public Type getGenericSuperclass() {
        GenericSignatureParser parser = new GenericSignatureParser(
                VMStack.getCallingClassLoader2());
        parser.parseForClass(this, getSignatureAttribute());
        return Types.getType(parser.superclassType);
    }

    /**
     * Returns an array of {@code Class} objects that match the interfaces
     * specified in the {@code implements} declaration of the class represented
     * by this {@code Class}. The order of the elements in the array is
     * identical to the order in the original class declaration. If the class
     * does not implement any interfaces, an empty array is returned.
     * 
     * @return an array with the interfaces of the class represented by this
     *         class.
     */
    public native Class[] getInterfaces();
    // BEGIN android-note
    // trying to get closer to the RI which returns a raw class array.
    // copied from newer version of harmony
    // END android-note

    // Changed to raw type to be closer to the RI
    /**
     * Returns a {@code Method} object which represents the public method with
     * the specified name and parameter types. This method first searches the
     * class C represented by this {@code Class}, then the superclasses of C and
     * finally the interfaces implemented by C and finally the superclasses of C
     * for a method with matching name.
     * 
     * @param name
     *            the requested method's name.
     * @param parameterTypes
     *            the parameter types of the requested method.
     *            {@code (Class[]) null} is equivalent to the empty array.
     * @return the public field specified by {@code name}.
     * @throws NoSuchMethodException
     *             if the method can not be found.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     * @see #getDeclaredMethod(String, Class...)
     */
    public Method getMethod(String name, Class... parameterTypes) throws NoSuchMethodException, 
            SecurityException {
        checkPublicMemberAccess();

        Method[] methods = getClassCache().getAllPublicMethods();
        Method method = findMethodByName(methods, name, parameterTypes);

        /*
         * Make a copy of the private (to the package) object, so that
         * setAccessible() won't alter the private instance.
         */
        return REFLECT.clone(method);
    }

    /**
     * Returns an array containing {@code Method} objects for all public methods
     * for the class C represented by this {@code Class}. Methods may be
     * declared in C, the interfaces it implements or in the superclasses of C.
     * The elements in the returned array are in no particular order.
     * <p>
     * If there are no public methods or if this {@code Class} represents a
     * primitive type or {@code void} then an empty array is returned.
     * </p>
     * 
     * @return an array with the methods of the class represented by this
     *         {@code Class}.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     * @see #getDeclaredMethods()
     */
    public Method[] getMethods() throws SecurityException {
        checkPublicMemberAccess();

        // Return a copy of the private (to the package) array.
        Method[] methods = getClassCache().getAllPublicMethods();
        return ClassCache.deepCopy(methods);
    }
    
    /**
     * Performs the security checks regarding the access of a public
     * member of this {@code Class}.
     * 
     * <p><b>Note:</b> Because of the {@code getCallingClassLoader2()}
     * check, this method must be called exactly one level deep into a
     * public method on this instance.</p>
     */
    /*package*/ void checkPublicMemberAccess() {
        SecurityManager smgr = System.getSecurityManager();

        if (smgr != null) {
            smgr.checkMemberAccess(this, Member.PUBLIC);

            ClassLoader calling = VMStack.getCallingClassLoader2();
            ClassLoader current = getClassLoader();
            
            if (calling != null && !calling.isAncestorOf(current)) {
                smgr.checkPackageAccess(this.getPackage().getName());
            }
        }
    }

    /**
     * Performs the security checks regarding the access of a declared
     * member of this {@code Class}.
     * 
     * <p><b>Note:</b> Because of the {@code getCallingClassLoader2()}
     * check, this method must be called exactly one level deep into a
     * public method on this instance.</p>
     */
    private void checkDeclaredMemberAccess() {
        SecurityManager smgr = System.getSecurityManager();
        if (smgr != null) {
            smgr.checkMemberAccess(this, Member.DECLARED);
            
            ClassLoader calling = VMStack.getCallingClassLoader2();
            ClassLoader current = getClassLoader();

            if (calling != null && !calling.isAncestorOf(current)) {
                smgr.checkPackageAccess(this.getPackage().getName());
            }
        }
    }
    
    /**
     * Returns an integer that represents the modifiers of the class represented
     * by this {@code Class}. The returned value is a combination of bits
     * defined by constants in the {@link Modifier} class.
     * 
     * @return the modifiers of the class represented by this {@code Class}.
     */
    public int getModifiers() {
        return getModifiers(this, false);
    }

    /*
     * Return the modifiers for the given class.
     * 
     * @param clazz the class of interest
     * @ignoreInnerClassesAttrib determines whether we look for and use the
     *     flags from an "inner class" attribute
     */
    private static native int getModifiers(Class<?> clazz, boolean ignoreInnerClassesAttrib);
    
    /**
     * Returns the name of the class represented by this {@code Class}. For a
     * description of the format which is used, see the class definition of
     * {@link Class}.
     * 
     * @return the name of the class represented by this {@code Class}.
     */
    public native String getName();

    /**
     * Returns the simple name of the class represented by this {@code Class} as
     * defined in the source code. If there is no name (that is, the class is
     * anonymous) then an empty string is returned. If the receiver is an array
     * then the name of the underlying type with square braces appended (for
     * example {@code &quot;Integer[]&quot;}) is returned.
     * 
     * @return the simple name of the class represented by this {@code Class}.
     */
    public String getSimpleName() {
        if (isArray()) {
            return getComponentType().getSimpleName() + "[]";
        }
        
        String name = getName();
        
        if (isAnonymousClass()) {
            return "";
        }

        if (isMemberClass() || isLocalClass()) {
            return getInnerClassName();
        }
        
        int dot = name.lastIndexOf('.');
        if (dot != -1) {
            return name.substring(dot + 1);
        }
        
        return name;
    }

    /*
     * Returns the simple name of a member or local class, or null otherwise. 
     * 
     * @return The name.
     */
    private native String getInnerClassName();
    
    /**
     * Returns the {@code ProtectionDomain} of the class represented by this
     * class.
     * <p>
     * Note: In order to conserve space in an embedded target like Android, we
     * allow this method to return {@code null} for classes in the system
     * protection domain (that is, for system classes). System classes are
     * always given full permissions (that is, AllPermission). This can not be
     * changed through the {@link java.security.Policy} class.
     * </p>
     * 
     * @return the {@code ProtectionDomain} of the class represented by this
     *         class.
     * @throws SecurityException
     *             if a security manager exists and it does not allow member
     *             access.
     */
    public ProtectionDomain getProtectionDomain() {
        SecurityManager smgr = System.getSecurityManager();
        if (smgr != null) {
            // Security check is independent of calling class loader.
            smgr.checkPermission(new RuntimePermission("getProtectionDomain"));
        }
        
        return pd;
    }

    /**
     * Returns the URL of the resource specified by {@code resName}. The mapping
     * between the resource name and the URL is managed by the class' class
     * loader.
     * 
     * @param resName
     *            the name of the resource.
     * @return the requested resource's {@code URL} object or {@code null} if
     *         the resource can not be found.
     * @see ClassLoader
     */
    public URL getResource(String resName) {
        // Get absolute resource name, but without the leading slash
        if (resName.startsWith("/")) {
            resName = resName.substring(1);
        } else {
            String pkg = getName();
            int dot = pkg.lastIndexOf('.');
            if (dot != -1) {
                pkg = pkg.substring(0, dot).replace('.', '/');
            } else {
                pkg = "";
            }
            
            resName = pkg + "/" + resName;
        }
        
        // Delegate to proper class loader
        ClassLoader loader = getClassLoader();
        if (loader != null) {
            return loader.getResource(resName);
        } else {
            return ClassLoader.getSystemResource(resName);
        }
    }

    /**
     * Returns a read-only stream for the contents of the resource specified by
     * {@code resName}. The mapping between the resource name and the stream is
     * managed by the class' class loader.
     * 
     * @param resName
     *            the name of the resource.
     * @return a stream for the requested resource or {@code null} if no
     *         resource with the specified name can be found.
     * @see ClassLoader
     */    
    public InputStream getResourceAsStream(String resName) {
        // Get absolute resource name, but without the leading slash
        if (resName.startsWith("/")) {
            resName = resName.substring(1);
        } else {
            String pkg = getName();
            int dot = pkg.lastIndexOf('.');
            if (dot != -1) {
                pkg = pkg.substring(0, dot).replace('.', '/');
            } else {
                pkg = "";
            }
            
            resName = pkg + "/" + resName;
        }
        
        // Delegate to proper class loader
        ClassLoader loader = getClassLoader();
        if (loader != null) {
            return loader.getResourceAsStream(resName);
        } else {
            return ClassLoader.getSystemResourceAsStream(resName);
        }
    }

    /**
     * Returns null. (On Android, a {@code ClassLoader} can load classes from multiple dex files.
     * All classes from any given dex file will have the same signers, but different dex
     * files may have different signers. This does not fit well with the original
     * {@code ClassLoader}-based model of {@code getSigners}.)
     * 
     * @return null.
     */
    public Object[] getSigners() {
        // See http://code.google.com/p/android/issues/detail?id=1766.
        return null;
    }

    /**
     * Returns the {@code Class} object which represents the superclass of the
     * class represented by this {@code Class}. If this {@code Class} represents
     * the {@code Object} class, a primitive type, an interface or void then the
     * method returns {@code null}. If this {@code Class} represents an array
     * class then the {@code Object} class is returned.
     * 
     * @return the superclass of the class represented by this {@code Class}.
     */
    public native Class<? super T> getSuperclass();

    /**
     * Returns an array containing {@code TypeVariable} objects for type
     * variables declared by the generic class represented by this {@code
     * Class}. Returns an empty array if the class is not generic.
     * 
     * @return an array with the type variables of the class represented by this
     *         class.
     */
    @SuppressWarnings("unchecked")
    public synchronized TypeVariable<Class<T>>[] getTypeParameters() {
        GenericSignatureParser parser = new GenericSignatureParser(
                VMStack.getCallingClassLoader2());
        parser.parseForClass(this, getSignatureAttribute());
        return parser.formalTypeParameters.clone();
    }

    /**
     * Indicates whether this {@code Class} represents an annotation class.
     * 
     * @return {@code true} if this {@code Class} represents an annotation
     *         class; {@code false} otherwise.
     */
    public boolean isAnnotation() {
        final int ACC_ANNOTATION = 0x2000;  // not public in reflect.Modifiers
        int mod = getModifiers(this, true);
        return (mod & ACC_ANNOTATION) != 0;
    }

    /**
     * Indicates whether the specified annotation is present for the class
     * represented by this {@code Class}.
     * 
     * @param annotationClass
     *            the annotation to look for.
     * @return {@code true} if the class represented by this {@code Class} is
     *         annotated with {@code annotationClass}; {@code false} otherwise.
     */
    public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
        return getAnnotation(annotationClass) != null;
    }

    /**
     * Indicates whether the class represented by this {@code Class} is
     * anonymously declared.
     * 
     * @return {@code true} if the class represented by this {@code Class} is
     *         anonymous; {@code false} otherwise.
     */
    native public boolean isAnonymousClass();

    /**
     * Indicates whether the class represented by this {@code Class} is an array
     * class.
     * 
     * @return {@code true} if the class represented by this {@code Class} is an
     *         array class; {@code false} otherwise.
     */
    public boolean isArray() {
        return getComponentType() != null;
    }

    /**
     * Indicates whether the specified class type can be converted to the class
     * represented by this {@code Class}. Conversion may be done via an identity
     * conversion or a widening reference conversion (if either the receiver or
     * the argument represent primitive types, only the identity conversion
     * applies).
     * 
     * @param cls
     *            the class to check.
     * @return {@code true} if {@code cls} can be converted to the class
     *         represented by this {@code Class}; {@code false} otherwise.
     * @throws NullPointerException
     *             if {@code cls} is {@code null}.
     */
    public native boolean isAssignableFrom(Class<?> cls);

    /**
     * Indicates whether the class represented by this {@code Class} is an
     * {@code enum}.
     * 
     * @return {@code true} if the class represented by this {@code Class} is an
     *         {@code enum}; {@code false} otherwise.
     */
    public boolean isEnum() {
        return ((getModifiers() & 0x4000) != 0) && (getSuperclass() == Enum.class);
    }

    /**
     * Indicates whether the specified object can be cast to the class
     * represented by this {@code Class}. This is the runtime version of the
     * {@code instanceof} operator.
     * 
     * @param object
     *            the object to check.
     * @return {@code true} if {@code object} can be cast to the type
     *         represented by this {@code Class}; {@code false} if {@code
     *         object} is {@code null} or cannot be cast.
     */
    public native boolean isInstance(Object object);

    /**
     * Indicates whether this {@code Class} represents an interface.
     * 
     * @return {@code true} if this {@code Class} represents an interface;
     *         {@code false} otherwise.
     */
    public native boolean isInterface();

    /**
     * Indicates whether the class represented by this {@code Class} is defined
     * locally.
     * 
     * @return {@code true} if the class represented by this {@code Class} is
     *         defined locally; {@code false} otherwise.
     */
    public boolean isLocalClass() {
        boolean enclosed = (getEnclosingMethod() != null ||
                         getEnclosingConstructor() != null);
        return enclosed && !isAnonymousClass();
    }

    /**
     * Indicates whether the class represented by this {@code Class} is a member
     * class.
     * 
     * @return {@code true} if the class represented by this {@code Class} is a
     *         member class; {@code false} otherwise.
     */
    public boolean isMemberClass() {
        return getDeclaringClass() != null;
    }

    /**
     * Indicates whether this {@code Class} represents a primitive type.
     * 
     * @return {@code true} if this {@code Class} represents a primitive type;
     *         {@code false} otherwise.
     */
    public native boolean isPrimitive();

    /**
     * Indicates whether this {@code Class} represents a synthetic type.
     * 
     * @return {@code true} if this {@code Class} represents a synthetic type;
     *         {@code false} otherwise.
     */
    public boolean isSynthetic() {
        final int ACC_SYNTHETIC = 0x1000;   // not public in reflect.Modifiers
        int mod = getModifiers(this, true);
        return (mod & ACC_SYNTHETIC) != 0;
    }

    /**
     * Returns a new instance of the class represented by this {@code Class},
     * created by invoking the default (that is, zero-argument) constructor. If
     * there is no such constructor, or if the creation fails (either because of
     * a lack of available memory or because an exception is thrown by the
     * constructor), an {@code InstantiationException} is thrown. If the default
     * constructor exists but is not accessible from the context where this
     * method is invoked, an {@code IllegalAccessException} is thrown.
     * 
     * @return a new instance of the class represented by this {@code Class}.
     * @throws IllegalAccessException
     *             if the default constructor is not visible.
     * @throws InstantiationException
     *             if the instance can not be created.
     * @throws SecurityException
     *             if a security manager exists and it does not allow creating
     *             new instances.
     */
    public T newInstance() throws InstantiationException, IllegalAccessException {
        checkPublicMemberAccess();        
        return newInstanceImpl();
    }

    private native T newInstanceImpl() throws IllegalAccessException,
            InstantiationException;

    @Override
    public String toString() {
        if (isPrimitive()) {
            return getSimpleName().toLowerCase();
        } else {
            return (isInterface() ? "interface " : "class ") + getName();
        }
    }

    /**
     * Returns the {@code Package} of which the class represented by this
     * {@code Class} is a member. Returns {@code null} if no {@code Package}
     * object was created by the class loader of the class.
     * 
     * @return Package the {@code Package} of which this {@code Class} is a
     *         member or {@code null}.
     */
    public Package getPackage() {
        // TODO This might be a hack, but the VM doesn't have the necessary info.
        ClassLoader loader = getClassLoader();
        if (loader != null) {
            String name = getName();
            int dot = name.lastIndexOf('.');
            return (dot != -1 ? ClassLoader.getPackage(loader, name.substring(0, dot)) : null);
        }
        
        return null;
    }

    /**
     * Returns the assertion status for the class represented by this {@code
     * Class}. Assertion is enabled / disabled based on the class loader,
     * package or class default at runtime.
     * 
     * @return the assertion status for the class represented by this {@code
     *         Class}.
     */
    public native boolean desiredAssertionStatus();

    /**
     * Casts this {@code Class} to represent a subclass of the specified class.
     * If successful, this {@code Class} is returned; otherwise a {@code
     * ClassCastException} is thrown.
     * 
     * @param clazz
     *            the required type.
     * @return this {@code Class} cast as a subclass of the given type.
     * @throws ClassCastException
     *             if this {@code Class} cannot be cast to the specified type.
     */
    @SuppressWarnings("unchecked")
    public <U> Class<? extends U> asSubclass(Class<U> clazz) {
        if (clazz.isAssignableFrom(this)) {
            return (Class<? extends U>)this;
        }
        throw new ClassCastException();
    }

    /**
     * Casts the specified object to the type represented by this {@code Class}.
     * If the object is {@code null} then the result is also {@code null}.
     * 
     * @param obj
     *            the object to cast.
     * @return the object that has been cast.
     * @throws ClassCastException
     *             if the object cannot be cast to the specified type.
     */
    @SuppressWarnings("unchecked")
    public T cast(Object obj) {
        if (obj == null) {
            return null;
        } else if (this.isInstance(obj)) {
            return (T)obj;            
        }
        throw new ClassCastException();
    }

    /**
     * Set the "accessible" flag of the given object, without doing any
     * access checks.
     * 
     * <p><b>Note:</b> This method is implemented in native code, and,
     * as such, is less efficient than using {@link ClassCache#REFLECT}
     * to achieve the same goal. This method exists solely to help
     * bootstrap the reflection bridge.</p>
     * 
     * @param ao non-null; the object to modify
     * @param flag the new value for the accessible flag
     */
    /*package*/ static native void setAccessibleNoCheck(AccessibleObject ao,
            boolean flag);
    
    /**
     * Copies two arrays into one. Assumes that the destination array is large
     * enough. 
     * 
     * @param result the destination array
     * @param head the first source array
     * @param tail the second source array
     * @return the destination array, that is, result
     */
    private static <T extends Object> T[] arraycopy(T[] result, T[] head, T[] tail) {
        System.arraycopy(head, 0, result, 0, head.length);
        System.arraycopy(tail, 0, result, head.length, tail.length);
        return result;
    }
    
    /**
     * This must be provided by the vm vendor, as it is used by other provided
     * class implementations in this package. This method is used by
     * SecurityManager.classDepth(), and getClassContext() which use the
     * parameters (-1, false) and SecurityManager.classLoaderDepth(),
     * currentClassLoader(), and currentLoadedClass() which use the parameters
     * (-1, true). Walk the stack and answer an array containing the maxDepth
     * most recent classes on the stack of the calling thread. Starting with the
     * caller of the caller of getStackClasses(), return an array of not more
     * than maxDepth Classes representing the classes of running methods on the
     * stack (including native methods). Frames representing the VM
     * implementation of java.lang.reflect are not included in the list. If
     * stopAtPrivileged is true, the walk will terminate at any frame running
     * one of the following methods: <code><ul>
     * <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedAction;)Ljava/lang/Object;</li>
     * <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object;</li>
     * <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;</li>
     * <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;</li>
     * </ul></code> If one of the doPrivileged methods is found, the walk terminate
     * and that frame is NOT included in the returned array. Notes:
     * <ul>
     * <li>This method operates on the defining classes of methods on stack.
     * NOT the classes of receivers.</li>
     * <li>The item at index zero in the result array describes the caller of
     * the caller of this method.</li>
     * </ul>
     * 
     * @param maxDepth
     *            maximum depth to walk the stack, -1 for the entire stack
     * @param stopAtPrivileged
     *            stop at privileged classes
     * @return the array of the most recent classes on the stack
     */
    static final Class<?>[] getStackClasses(int maxDepth, boolean stopAtPrivileged) {
        return VMStack.getClasses(maxDepth, stopAtPrivileged);
    }
    
}
