jaroslav@56: /* jaroslav@56: * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. jaroslav@56: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@56: * jaroslav@56: * This code is free software; you can redistribute it and/or modify it jaroslav@56: * under the terms of the GNU General Public License version 2 only, as jaroslav@56: * published by the Free Software Foundation. Oracle designates this jaroslav@56: * particular file as subject to the "Classpath" exception as provided jaroslav@56: * by Oracle in the LICENSE file that accompanied this code. jaroslav@56: * jaroslav@56: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@56: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@56: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@56: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@56: * accompanied this code). jaroslav@56: * jaroslav@56: * You should have received a copy of the GNU General Public License version jaroslav@56: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@56: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@56: * jaroslav@56: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@56: * or visit www.oracle.com if you need additional information or have any jaroslav@56: * questions. jaroslav@56: */ jaroslav@56: jaroslav@56: package java.lang; jaroslav@56: jaroslav@56: import java.lang.reflect.Array; jaroslav@56: import java.lang.reflect.GenericArrayType; jaroslav@56: import java.lang.reflect.Member; jaroslav@56: import java.lang.reflect.Field; jaroslav@56: import java.lang.reflect.Method; jaroslav@56: import java.lang.reflect.Constructor; jaroslav@56: import java.lang.reflect.GenericDeclaration; jaroslav@56: import java.lang.reflect.Modifier; jaroslav@56: import java.lang.reflect.Type; jaroslav@56: import java.lang.reflect.TypeVariable; jaroslav@56: import java.lang.reflect.InvocationTargetException; jaroslav@56: import java.lang.ref.SoftReference; jaroslav@56: import java.io.InputStream; jaroslav@56: import java.io.ObjectStreamField; jaroslav@56: import java.security.AccessController; jaroslav@56: import java.security.PrivilegedAction; jaroslav@56: import java.util.ArrayList; jaroslav@56: import java.util.Arrays; jaroslav@56: import java.util.Collection; jaroslav@56: import java.util.HashSet; jaroslav@56: import java.util.Iterator; jaroslav@56: import java.util.List; jaroslav@56: import java.util.LinkedList; jaroslav@56: import java.util.LinkedHashSet; jaroslav@56: import java.util.Set; jaroslav@56: import java.util.Map; jaroslav@56: import java.util.HashMap; jaroslav@56: import sun.misc.Unsafe; jaroslav@56: import sun.reflect.ConstantPool; jaroslav@56: import sun.reflect.Reflection; jaroslav@56: import sun.reflect.ReflectionFactory; jaroslav@56: import sun.reflect.SignatureIterator; jaroslav@56: import sun.reflect.generics.factory.CoreReflectionFactory; jaroslav@56: import sun.reflect.generics.factory.GenericsFactory; jaroslav@56: import sun.reflect.generics.repository.ClassRepository; jaroslav@56: import sun.reflect.generics.repository.MethodRepository; jaroslav@56: import sun.reflect.generics.repository.ConstructorRepository; jaroslav@56: import sun.reflect.generics.scope.ClassScope; jaroslav@56: import sun.security.util.SecurityConstants; jaroslav@56: import java.lang.annotation.Annotation; jaroslav@56: import sun.reflect.annotation.*; jaroslav@56: jaroslav@56: /** jaroslav@56: * Instances of the class {@code Class} represent classes and jaroslav@56: * interfaces in a running Java application. An enum is a kind of jaroslav@56: * class and an annotation is a kind of interface. Every array also jaroslav@56: * belongs to a class that is reflected as a {@code Class} object jaroslav@56: * that is shared by all arrays with the same element type and number jaroslav@56: * of dimensions. The primitive Java types ({@code boolean}, jaroslav@56: * {@code byte}, {@code char}, {@code short}, jaroslav@56: * {@code int}, {@code long}, {@code float}, and jaroslav@56: * {@code double}), and the keyword {@code void} are also jaroslav@56: * represented as {@code Class} objects. jaroslav@56: * jaroslav@56: *

{@code Class} has no public constructor. Instead {@code Class} jaroslav@56: * objects are constructed automatically by the Java Virtual Machine as classes jaroslav@56: * are loaded and by calls to the {@code defineClass} method in the class jaroslav@56: * loader. jaroslav@56: * jaroslav@56: *

The following example uses a {@code Class} object to print the jaroslav@56: * class name of an object: jaroslav@56: * jaroslav@56: *

jaroslav@56:  *     void printClassName(Object obj) {
jaroslav@56:  *         System.out.println("The class of " + obj +
jaroslav@56:  *                            " is " + obj.getClass().getName());
jaroslav@56:  *     }
jaroslav@56:  * 
jaroslav@56: * jaroslav@56: *

It is also possible to get the {@code Class} object for a named jaroslav@56: * type (or for void) using a class literal. See Section 15.8.2 of jaroslav@56: * The Java™ Language Specification. jaroslav@56: * For example: jaroslav@56: * jaroslav@56: *

jaroslav@56: * {@code System.out.println("The name of class Foo is: "+Foo.class.getName());} jaroslav@56: *
jaroslav@56: * jaroslav@56: * @param the type of the class modeled by this {@code Class} jaroslav@56: * object. For example, the type of {@code String.class} is {@code jaroslav@56: * Class}. Use {@code Class} if the class being modeled is jaroslav@56: * unknown. jaroslav@56: * jaroslav@56: * @author unascribed jaroslav@56: * @see java.lang.ClassLoader#defineClass(byte[], int, int) jaroslav@56: * @since JDK1.0 jaroslav@56: */ jaroslav@56: public final jaroslav@56: class Class implements java.io.Serializable, jaroslav@56: java.lang.reflect.GenericDeclaration, jaroslav@56: java.lang.reflect.Type, jaroslav@56: java.lang.reflect.AnnotatedElement { jaroslav@56: private static final int ANNOTATION= 0x00002000; jaroslav@56: private static final int ENUM = 0x00004000; jaroslav@56: private static final int SYNTHETIC = 0x00001000; jaroslav@56: jaroslav@56: private static native void registerNatives(); jaroslav@56: static { jaroslav@56: registerNatives(); jaroslav@56: } jaroslav@56: jaroslav@56: /* jaroslav@56: * Constructor. Only the Java Virtual Machine creates Class jaroslav@56: * objects. jaroslav@56: */ jaroslav@56: private Class() {} jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Converts the object to a string. The string representation is the jaroslav@56: * string "class" or "interface", followed by a space, and then by the jaroslav@56: * fully qualified name of the class in the format returned by jaroslav@56: * {@code getName}. If this {@code Class} object represents a jaroslav@56: * primitive type, this method returns the name of the primitive type. If jaroslav@56: * this {@code Class} object represents void this method returns jaroslav@56: * "void". jaroslav@56: * jaroslav@56: * @return a string representation of this class object. jaroslav@56: */ jaroslav@56: public String toString() { jaroslav@56: return (isInterface() ? "interface " : (isPrimitive() ? "" : "class ")) jaroslav@56: + getName(); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the {@code Class} object associated with the class or jaroslav@56: * interface with the given string name. Invoking this method is jaroslav@56: * equivalent to: jaroslav@56: * jaroslav@56: *
jaroslav@56: * {@code Class.forName(className, true, currentLoader)} jaroslav@56: *
jaroslav@56: * jaroslav@56: * where {@code currentLoader} denotes the defining class loader of jaroslav@56: * the current class. jaroslav@56: * jaroslav@56: *

For example, the following code fragment returns the jaroslav@56: * runtime {@code Class} descriptor for the class named jaroslav@56: * {@code java.lang.Thread}: jaroslav@56: * jaroslav@56: *

jaroslav@56: * {@code Class t = Class.forName("java.lang.Thread")} jaroslav@56: *
jaroslav@56: *

jaroslav@56: * A call to {@code forName("X")} causes the class named jaroslav@56: * {@code X} to be initialized. jaroslav@56: * jaroslav@56: * @param className the fully qualified name of the desired class. jaroslav@56: * @return the {@code Class} object for the class with the jaroslav@56: * specified name. jaroslav@56: * @exception LinkageError if the linkage fails jaroslav@56: * @exception ExceptionInInitializerError if the initialization provoked jaroslav@56: * by this method fails jaroslav@56: * @exception ClassNotFoundException if the class cannot be located jaroslav@56: */ jaroslav@56: public static Class forName(String className) jaroslav@56: throws ClassNotFoundException { jaroslav@56: return forName0(className, true, ClassLoader.getCallerClassLoader()); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the {@code Class} object associated with the class or jaroslav@56: * interface with the given string name, using the given class loader. jaroslav@56: * Given the fully qualified name for a class or interface (in the same jaroslav@56: * format returned by {@code getName}) this method attempts to jaroslav@56: * locate, load, and link the class or interface. The specified class jaroslav@56: * loader is used to load the class or interface. If the parameter jaroslav@56: * {@code loader} is null, the class is loaded through the bootstrap jaroslav@56: * class loader. The class is initialized only if the jaroslav@56: * {@code initialize} parameter is {@code true} and if it has jaroslav@56: * not been initialized earlier. jaroslav@56: * jaroslav@56: *

If {@code name} denotes a primitive type or void, an attempt jaroslav@56: * will be made to locate a user-defined class in the unnamed package whose jaroslav@56: * name is {@code name}. Therefore, this method cannot be used to jaroslav@56: * obtain any of the {@code Class} objects representing primitive jaroslav@56: * types or void. jaroslav@56: * jaroslav@56: *

If {@code name} denotes an array class, the component type of jaroslav@56: * the array class is loaded but not initialized. jaroslav@56: * jaroslav@56: *

For example, in an instance method the expression: jaroslav@56: * jaroslav@56: *

jaroslav@56: * {@code Class.forName("Foo")} jaroslav@56: *
jaroslav@56: * jaroslav@56: * is equivalent to: jaroslav@56: * jaroslav@56: *
jaroslav@56: * {@code Class.forName("Foo", true, this.getClass().getClassLoader())} jaroslav@56: *
jaroslav@56: * jaroslav@56: * Note that this method throws errors related to loading, linking or jaroslav@56: * initializing as specified in Sections 12.2, 12.3 and 12.4 of The jaroslav@56: * Java Language Specification. jaroslav@56: * Note that this method does not check whether the requested class jaroslav@56: * is accessible to its caller. jaroslav@56: * jaroslav@56: *

If the {@code loader} is {@code null}, and a security jaroslav@56: * manager is present, and the caller's class loader is not null, then this jaroslav@56: * method calls the security manager's {@code checkPermission} method jaroslav@56: * with a {@code RuntimePermission("getClassLoader")} permission to jaroslav@56: * ensure it's ok to access the bootstrap class loader. jaroslav@56: * jaroslav@56: * @param name fully qualified name of the desired class jaroslav@56: * @param initialize whether the class must be initialized jaroslav@56: * @param loader class loader from which the class must be loaded jaroslav@56: * @return class object representing the desired class jaroslav@56: * jaroslav@56: * @exception LinkageError if the linkage fails jaroslav@56: * @exception ExceptionInInitializerError if the initialization provoked jaroslav@56: * by this method fails jaroslav@56: * @exception ClassNotFoundException if the class cannot be located by jaroslav@56: * the specified class loader jaroslav@56: * jaroslav@56: * @see java.lang.Class#forName(String) jaroslav@56: * @see java.lang.ClassLoader jaroslav@56: * @since 1.2 jaroslav@56: */ jaroslav@56: public static Class forName(String name, boolean initialize, jaroslav@56: ClassLoader loader) jaroslav@56: throws ClassNotFoundException jaroslav@56: { jaroslav@56: if (loader == null) { jaroslav@56: SecurityManager sm = System.getSecurityManager(); jaroslav@56: if (sm != null) { jaroslav@56: ClassLoader ccl = ClassLoader.getCallerClassLoader(); jaroslav@56: if (ccl != null) { jaroslav@56: sm.checkPermission( jaroslav@56: SecurityConstants.GET_CLASSLOADER_PERMISSION); jaroslav@56: } jaroslav@56: } jaroslav@56: } jaroslav@56: return forName0(name, initialize, loader); jaroslav@56: } jaroslav@56: jaroslav@56: /** Called after security checks have been made. */ jaroslav@56: private static native Class forName0(String name, boolean initialize, jaroslav@56: ClassLoader loader) jaroslav@56: throws ClassNotFoundException; jaroslav@56: jaroslav@56: /** jaroslav@56: * Creates a new instance of the class represented by this {@code Class} jaroslav@56: * object. The class is instantiated as if by a {@code new} jaroslav@56: * expression with an empty argument list. The class is initialized if it jaroslav@56: * has not already been initialized. jaroslav@56: * jaroslav@56: *

Note that this method propagates any exception thrown by the jaroslav@56: * nullary constructor, including a checked exception. Use of jaroslav@56: * this method effectively bypasses the compile-time exception jaroslav@56: * checking that would otherwise be performed by the compiler. jaroslav@56: * The {@link jaroslav@56: * java.lang.reflect.Constructor#newInstance(java.lang.Object...) jaroslav@56: * Constructor.newInstance} method avoids this problem by wrapping jaroslav@56: * any exception thrown by the constructor in a (checked) {@link jaroslav@56: * java.lang.reflect.InvocationTargetException}. jaroslav@56: * jaroslav@56: * @return a newly allocated instance of the class represented by this jaroslav@56: * object. jaroslav@56: * @exception IllegalAccessException if the class or its nullary jaroslav@56: * constructor is not accessible. jaroslav@56: * @exception InstantiationException jaroslav@56: * if this {@code Class} represents an abstract class, jaroslav@56: * an interface, an array class, a primitive type, or void; jaroslav@56: * or if the class has no nullary constructor; jaroslav@56: * or if the instantiation fails for some other reason. jaroslav@56: * @exception ExceptionInInitializerError if the initialization jaroslav@56: * provoked by this method fails. jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *

    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.PUBLIC)} denies jaroslav@56: * creation of new instances of this class jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: */ jaroslav@56: public T newInstance() jaroslav@56: throws InstantiationException, IllegalAccessException jaroslav@56: { jaroslav@56: if (System.getSecurityManager() != null) { jaroslav@56: checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); jaroslav@56: } jaroslav@56: return newInstance0(); jaroslav@56: } jaroslav@56: jaroslav@56: private T newInstance0() jaroslav@56: throws InstantiationException, IllegalAccessException jaroslav@56: { jaroslav@56: // NOTE: the following code may not be strictly correct under jaroslav@56: // the current Java memory model. jaroslav@56: jaroslav@56: // Constructor lookup jaroslav@56: if (cachedConstructor == null) { jaroslav@56: if (this == Class.class) { jaroslav@56: throw new IllegalAccessException( jaroslav@56: "Can not call newInstance() on the Class for java.lang.Class" jaroslav@56: ); jaroslav@56: } jaroslav@56: try { jaroslav@56: Class[] empty = {}; jaroslav@56: final Constructor c = getConstructor0(empty, Member.DECLARED); jaroslav@56: // Disable accessibility checks on the constructor jaroslav@56: // since we have to do the security check here anyway jaroslav@56: // (the stack depth is wrong for the Constructor's jaroslav@56: // security check to work) jaroslav@56: java.security.AccessController.doPrivileged( jaroslav@56: new java.security.PrivilegedAction() { jaroslav@56: public Void run() { jaroslav@56: c.setAccessible(true); jaroslav@56: return null; jaroslav@56: } jaroslav@56: }); jaroslav@56: cachedConstructor = c; jaroslav@56: } catch (NoSuchMethodException e) { jaroslav@56: throw new InstantiationException(getName()); jaroslav@56: } jaroslav@56: } jaroslav@56: Constructor tmpConstructor = cachedConstructor; jaroslav@56: // Security check (same as in java.lang.reflect.Constructor) jaroslav@56: int modifiers = tmpConstructor.getModifiers(); jaroslav@56: if (!Reflection.quickCheckMemberAccess(this, modifiers)) { jaroslav@56: Class caller = Reflection.getCallerClass(3); jaroslav@56: if (newInstanceCallerCache != caller) { jaroslav@56: Reflection.ensureMemberAccess(caller, this, null, modifiers); jaroslav@56: newInstanceCallerCache = caller; jaroslav@56: } jaroslav@56: } jaroslav@56: // Run constructor jaroslav@56: try { jaroslav@56: return tmpConstructor.newInstance((Object[])null); jaroslav@56: } catch (InvocationTargetException e) { jaroslav@56: Unsafe.getUnsafe().throwException(e.getTargetException()); jaroslav@56: // Not reached jaroslav@56: return null; jaroslav@56: } jaroslav@56: } jaroslav@56: private volatile transient Constructor cachedConstructor; jaroslav@56: private volatile transient Class newInstanceCallerCache; jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Determines if the specified {@code Object} is assignment-compatible jaroslav@56: * with the object represented by this {@code Class}. This method is jaroslav@56: * the dynamic equivalent of the Java language {@code instanceof} jaroslav@56: * operator. The method returns {@code true} if the specified jaroslav@56: * {@code Object} argument is non-null and can be cast to the jaroslav@56: * reference type represented by this {@code Class} object without jaroslav@56: * raising a {@code ClassCastException.} It returns {@code false} jaroslav@56: * otherwise. jaroslav@56: * jaroslav@56: *

Specifically, if this {@code Class} object represents a jaroslav@56: * declared class, this method returns {@code true} if the specified jaroslav@56: * {@code Object} argument is an instance of the represented class (or jaroslav@56: * of any of its subclasses); it returns {@code false} otherwise. If jaroslav@56: * this {@code Class} object represents an array class, this method jaroslav@56: * returns {@code true} if the specified {@code Object} argument jaroslav@56: * can be converted to an object of the array class by an identity jaroslav@56: * conversion or by a widening reference conversion; it returns jaroslav@56: * {@code false} otherwise. If this {@code Class} object jaroslav@56: * represents an interface, this method returns {@code true} if the jaroslav@56: * class or any superclass of the specified {@code Object} argument jaroslav@56: * implements this interface; it returns {@code false} otherwise. If jaroslav@56: * this {@code Class} object represents a primitive type, this method jaroslav@56: * returns {@code false}. jaroslav@56: * jaroslav@56: * @param obj the object to check jaroslav@56: * @return true if {@code obj} is an instance of this class jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public native boolean isInstance(Object obj); jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Determines if the class or interface represented by this jaroslav@56: * {@code Class} object is either the same as, or is a superclass or jaroslav@56: * superinterface of, the class or interface represented by the specified jaroslav@56: * {@code Class} parameter. It returns {@code true} if so; jaroslav@56: * otherwise it returns {@code false}. If this {@code Class} jaroslav@56: * object represents a primitive type, this method returns jaroslav@56: * {@code true} if the specified {@code Class} parameter is jaroslav@56: * exactly this {@code Class} object; otherwise it returns jaroslav@56: * {@code false}. jaroslav@56: * jaroslav@56: *

Specifically, this method tests whether the type represented by the jaroslav@56: * specified {@code Class} parameter can be converted to the type jaroslav@56: * represented by this {@code Class} object via an identity conversion jaroslav@56: * or via a widening reference conversion. See The Java Language jaroslav@56: * Specification, sections 5.1.1 and 5.1.4 , for details. jaroslav@56: * jaroslav@56: * @param cls the {@code Class} object to be checked jaroslav@56: * @return the {@code boolean} value indicating whether objects of the jaroslav@56: * type {@code cls} can be assigned to objects of this class jaroslav@56: * @exception NullPointerException if the specified Class parameter is jaroslav@56: * null. jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public native boolean isAssignableFrom(Class cls); jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Determines if the specified {@code Class} object represents an jaroslav@56: * interface type. jaroslav@56: * jaroslav@56: * @return {@code true} if this object represents an interface; jaroslav@56: * {@code false} otherwise. jaroslav@56: */ jaroslav@56: public native boolean isInterface(); jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Determines if this {@code Class} object represents an array class. jaroslav@56: * jaroslav@56: * @return {@code true} if this object represents an array class; jaroslav@56: * {@code false} otherwise. jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public native boolean isArray(); jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Determines if the specified {@code Class} object represents a jaroslav@56: * primitive type. jaroslav@56: * jaroslav@56: *

There are nine predefined {@code Class} objects to represent jaroslav@56: * the eight primitive types and void. These are created by the Java jaroslav@56: * Virtual Machine, and have the same names as the primitive types that jaroslav@56: * they represent, namely {@code boolean}, {@code byte}, jaroslav@56: * {@code char}, {@code short}, {@code int}, jaroslav@56: * {@code long}, {@code float}, and {@code double}. jaroslav@56: * jaroslav@56: *

These objects may only be accessed via the following public static jaroslav@56: * final variables, and are the only {@code Class} objects for which jaroslav@56: * this method returns {@code true}. jaroslav@56: * jaroslav@56: * @return true if and only if this class represents a primitive type jaroslav@56: * jaroslav@56: * @see java.lang.Boolean#TYPE jaroslav@56: * @see java.lang.Character#TYPE jaroslav@56: * @see java.lang.Byte#TYPE jaroslav@56: * @see java.lang.Short#TYPE jaroslav@56: * @see java.lang.Integer#TYPE jaroslav@56: * @see java.lang.Long#TYPE jaroslav@56: * @see java.lang.Float#TYPE jaroslav@56: * @see java.lang.Double#TYPE jaroslav@56: * @see java.lang.Void#TYPE jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public native boolean isPrimitive(); jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns true if this {@code Class} object represents an annotation jaroslav@56: * type. Note that if this method returns true, {@link #isInterface()} jaroslav@56: * would also return true, as all annotation types are also interfaces. jaroslav@56: * jaroslav@56: * @return {@code true} if this class object represents an annotation jaroslav@56: * type; {@code false} otherwise jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public boolean isAnnotation() { jaroslav@56: return (getModifiers() & ANNOTATION) != 0; jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns {@code true} if this class is a synthetic class; jaroslav@56: * returns {@code false} otherwise. jaroslav@56: * @return {@code true} if and only if this class is a synthetic class as jaroslav@56: * defined by the Java Language Specification. jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public boolean isSynthetic() { jaroslav@56: return (getModifiers() & SYNTHETIC) != 0; jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the name of the entity (class, interface, array class, jaroslav@56: * primitive type, or void) represented by this {@code Class} object, jaroslav@56: * as a {@code String}. jaroslav@56: * jaroslav@56: *

If this class object represents a reference type that is not an jaroslav@56: * array type then the binary name of the class is returned, as specified jaroslav@56: * by jaroslav@56: * The Java™ Language Specification. jaroslav@56: * jaroslav@56: *

If this class object represents a primitive type or void, then the jaroslav@56: * name returned is a {@code String} equal to the Java language jaroslav@56: * keyword corresponding to the primitive type or void. jaroslav@56: * jaroslav@56: *

If this class object represents a class of arrays, then the internal jaroslav@56: * form of the name consists of the name of the element type preceded by jaroslav@56: * one or more '{@code [}' characters representing the depth of the array jaroslav@56: * nesting. The encoding of element type names is as follows: jaroslav@56: * jaroslav@56: *

jaroslav@56: *
Element Type     Encoding jaroslav@56: *
boolean     Z jaroslav@56: *
byte     B jaroslav@56: *
char     C jaroslav@56: *
class or interface jaroslav@56: *     Lclassname; jaroslav@56: *
double     D jaroslav@56: *
float     F jaroslav@56: *
int     I jaroslav@56: *
long     J jaroslav@56: *
short     S jaroslav@56: *
jaroslav@56: * jaroslav@56: *

The class or interface name classname is the binary name of jaroslav@56: * the class specified above. jaroslav@56: * jaroslav@56: *

Examples: jaroslav@56: *

jaroslav@56:      * String.class.getName()
jaroslav@56:      *     returns "java.lang.String"
jaroslav@56:      * byte.class.getName()
jaroslav@56:      *     returns "byte"
jaroslav@56:      * (new Object[3]).getClass().getName()
jaroslav@56:      *     returns "[Ljava.lang.Object;"
jaroslav@56:      * (new int[3][4][5][6][7][8][9]).getClass().getName()
jaroslav@56:      *     returns "[[[[[[[I"
jaroslav@56:      * 
jaroslav@56: * jaroslav@56: * @return the name of the class or interface jaroslav@56: * represented by this object. jaroslav@56: */ jaroslav@56: public String getName() { jaroslav@56: String name = this.name; jaroslav@56: if (name == null) jaroslav@56: this.name = name = getName0(); jaroslav@56: return name; jaroslav@56: } jaroslav@56: jaroslav@56: // cache the name to reduce the number of calls into the VM jaroslav@56: private transient String name; jaroslav@56: private native String getName0(); jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the class loader for the class. Some implementations may use jaroslav@56: * null to represent the bootstrap class loader. This method will return jaroslav@56: * null in such implementations if this class was loaded by the bootstrap jaroslav@56: * class loader. jaroslav@56: * jaroslav@56: *

If a security manager is present, and the caller's class loader is jaroslav@56: * not null and the caller's class loader is not the same as or an ancestor of jaroslav@56: * the class loader for the class whose class loader is requested, then jaroslav@56: * this method calls the security manager's {@code checkPermission} jaroslav@56: * method with a {@code RuntimePermission("getClassLoader")} jaroslav@56: * permission to ensure it's ok to access the class loader for the class. jaroslav@56: * jaroslav@56: *

If this object jaroslav@56: * represents a primitive type or void, null is returned. jaroslav@56: * jaroslav@56: * @return the class loader that loaded the class or interface jaroslav@56: * represented by this object. jaroslav@56: * @throws SecurityException jaroslav@56: * if a security manager exists and its jaroslav@56: * {@code checkPermission} method denies jaroslav@56: * access to the class loader for the class. jaroslav@56: * @see java.lang.ClassLoader jaroslav@56: * @see SecurityManager#checkPermission jaroslav@56: * @see java.lang.RuntimePermission jaroslav@56: */ jaroslav@56: public ClassLoader getClassLoader() { jaroslav@56: ClassLoader cl = getClassLoader0(); jaroslav@56: if (cl == null) jaroslav@56: return null; jaroslav@56: SecurityManager sm = System.getSecurityManager(); jaroslav@56: if (sm != null) { jaroslav@56: ClassLoader ccl = ClassLoader.getCallerClassLoader(); jaroslav@56: if (ccl != null && ccl != cl && !cl.isAncestor(ccl)) { jaroslav@56: sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); jaroslav@56: } jaroslav@56: } jaroslav@56: return cl; jaroslav@56: } jaroslav@56: jaroslav@56: // Package-private to allow ClassLoader access jaroslav@56: native ClassLoader getClassLoader0(); jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns an array of {@code TypeVariable} objects that represent the jaroslav@56: * type variables declared by the generic declaration represented by this jaroslav@56: * {@code GenericDeclaration} object, in declaration order. Returns an jaroslav@56: * array of length 0 if the underlying generic declaration declares no type jaroslav@56: * variables. jaroslav@56: * jaroslav@56: * @return an array of {@code TypeVariable} objects that represent jaroslav@56: * the type variables declared by this generic declaration jaroslav@56: * @throws java.lang.reflect.GenericSignatureFormatError if the generic jaroslav@56: * signature of this generic declaration does not conform to jaroslav@56: * the format specified in jaroslav@56: * The Java™ Virtual Machine Specification jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public TypeVariable>[] getTypeParameters() { jaroslav@56: if (getGenericSignature() != null) jaroslav@56: return (TypeVariable>[])getGenericInfo().getTypeParameters(); jaroslav@56: else jaroslav@56: return (TypeVariable>[])new TypeVariable[0]; jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the {@code Class} representing the superclass of the entity jaroslav@56: * (class, interface, primitive type or void) represented by this jaroslav@56: * {@code Class}. If this {@code Class} represents either the jaroslav@56: * {@code Object} class, an interface, a primitive type, or void, then jaroslav@56: * null is returned. If this object represents an array class then the jaroslav@56: * {@code Class} object representing the {@code Object} class is jaroslav@56: * returned. jaroslav@56: * jaroslav@56: * @return the superclass of the class represented by this object. jaroslav@56: */ jaroslav@56: public native Class getSuperclass(); jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the {@code Type} representing the direct superclass of jaroslav@56: * the entity (class, interface, primitive type or void) represented by jaroslav@56: * this {@code Class}. jaroslav@56: * jaroslav@56: *

If the superclass is a parameterized type, the {@code Type} jaroslav@56: * object returned must accurately reflect the actual type jaroslav@56: * parameters used in the source code. The parameterized type jaroslav@56: * representing the superclass is created if it had not been jaroslav@56: * created before. See the declaration of {@link jaroslav@56: * java.lang.reflect.ParameterizedType ParameterizedType} for the jaroslav@56: * semantics of the creation process for parameterized types. If jaroslav@56: * this {@code Class} represents either the {@code Object} jaroslav@56: * class, an interface, a primitive type, or void, then null is jaroslav@56: * returned. If this object represents an array class then the jaroslav@56: * {@code Class} object representing the {@code Object} class is jaroslav@56: * returned. jaroslav@56: * jaroslav@56: * @throws java.lang.reflect.GenericSignatureFormatError if the generic jaroslav@56: * class signature does not conform to the format specified in jaroslav@56: * The Java™ Virtual Machine Specification jaroslav@56: * @throws TypeNotPresentException if the generic superclass jaroslav@56: * refers to a non-existent type declaration jaroslav@56: * @throws java.lang.reflect.MalformedParameterizedTypeException if the jaroslav@56: * generic superclass refers to a parameterized type that cannot be jaroslav@56: * instantiated for any reason jaroslav@56: * @return the superclass of the class represented by this object jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public Type getGenericSuperclass() { jaroslav@56: if (getGenericSignature() != null) { jaroslav@56: // Historical irregularity: jaroslav@56: // Generic signature marks interfaces with superclass = Object jaroslav@56: // but this API returns null for interfaces jaroslav@56: if (isInterface()) jaroslav@56: return null; jaroslav@56: return getGenericInfo().getSuperclass(); jaroslav@56: } else jaroslav@56: return getSuperclass(); jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Gets the package for this class. The class loader of this class is used jaroslav@56: * to find the package. If the class was loaded by the bootstrap class jaroslav@56: * loader the set of packages loaded from CLASSPATH is searched to find the jaroslav@56: * package of the class. Null is returned if no package object was created jaroslav@56: * by the class loader of this class. jaroslav@56: * jaroslav@56: *

Packages have attributes for versions and specifications only if the jaroslav@56: * information was defined in the manifests that accompany the classes, and jaroslav@56: * if the class loader created the package instance with the attributes jaroslav@56: * from the manifest. jaroslav@56: * jaroslav@56: * @return the package of the class, or null if no package jaroslav@56: * information is available from the archive or codebase. jaroslav@56: */ jaroslav@56: public Package getPackage() { jaroslav@56: return Package.getPackage(this); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Determines the interfaces implemented by the class or interface jaroslav@56: * represented by this object. jaroslav@56: * jaroslav@56: *

If this object represents a class, the return value is an array jaroslav@56: * containing objects representing all interfaces implemented by the jaroslav@56: * class. The order of the interface objects in the array corresponds to jaroslav@56: * the order of the interface names in the {@code implements} clause jaroslav@56: * of the declaration of the class represented by this object. For jaroslav@56: * example, given the declaration: jaroslav@56: *

jaroslav@56: * {@code class Shimmer implements FloorWax, DessertTopping { ... }} jaroslav@56: *
jaroslav@56: * suppose the value of {@code s} is an instance of jaroslav@56: * {@code Shimmer}; the value of the expression: jaroslav@56: *
jaroslav@56: * {@code s.getClass().getInterfaces()[0]} jaroslav@56: *
jaroslav@56: * is the {@code Class} object that represents interface jaroslav@56: * {@code FloorWax}; and the value of: jaroslav@56: *
jaroslav@56: * {@code s.getClass().getInterfaces()[1]} jaroslav@56: *
jaroslav@56: * is the {@code Class} object that represents interface jaroslav@56: * {@code DessertTopping}. jaroslav@56: * jaroslav@56: *

If this object represents an interface, the array contains objects jaroslav@56: * representing all interfaces extended by the interface. The order of the jaroslav@56: * interface objects in the array corresponds to the order of the interface jaroslav@56: * names in the {@code extends} clause of the declaration of the jaroslav@56: * interface represented by this object. jaroslav@56: * jaroslav@56: *

If this object represents a class or interface that implements no jaroslav@56: * interfaces, the method returns an array of length 0. jaroslav@56: * jaroslav@56: *

If this object represents a primitive type or void, the method jaroslav@56: * returns an array of length 0. jaroslav@56: * jaroslav@56: * @return an array of interfaces implemented by this class. jaroslav@56: */ jaroslav@56: public native Class[] getInterfaces(); jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the {@code Type}s representing the interfaces jaroslav@56: * directly implemented by the class or interface represented by jaroslav@56: * this object. jaroslav@56: * jaroslav@56: *

If a superinterface is a parameterized type, the jaroslav@56: * {@code Type} object returned for it must accurately reflect jaroslav@56: * the actual type parameters used in the source code. The jaroslav@56: * parameterized type representing each superinterface is created jaroslav@56: * if it had not been created before. See the declaration of jaroslav@56: * {@link java.lang.reflect.ParameterizedType ParameterizedType} jaroslav@56: * for the semantics of the creation process for parameterized jaroslav@56: * types. jaroslav@56: * jaroslav@56: *

If this object represents a class, the return value is an jaroslav@56: * array containing objects representing all interfaces jaroslav@56: * implemented by the class. The order of the interface objects in jaroslav@56: * the array corresponds to the order of the interface names in jaroslav@56: * the {@code implements} clause of the declaration of the class jaroslav@56: * represented by this object. In the case of an array class, the jaroslav@56: * interfaces {@code Cloneable} and {@code Serializable} are jaroslav@56: * returned in that order. jaroslav@56: * jaroslav@56: *

If this object represents an interface, the array contains jaroslav@56: * objects representing all interfaces directly extended by the jaroslav@56: * interface. The order of the interface objects in the array jaroslav@56: * corresponds to the order of the interface names in the jaroslav@56: * {@code extends} clause of the declaration of the interface jaroslav@56: * represented by this object. jaroslav@56: * jaroslav@56: *

If this object represents a class or interface that jaroslav@56: * implements no interfaces, the method returns an array of length jaroslav@56: * 0. jaroslav@56: * jaroslav@56: *

If this object represents a primitive type or void, the jaroslav@56: * method returns an array of length 0. jaroslav@56: * jaroslav@56: * @throws java.lang.reflect.GenericSignatureFormatError jaroslav@56: * if the generic class signature does not conform to the format jaroslav@56: * specified in jaroslav@56: * The Java™ Virtual Machine Specification jaroslav@56: * @throws TypeNotPresentException if any of the generic jaroslav@56: * superinterfaces refers to a non-existent type declaration jaroslav@56: * @throws java.lang.reflect.MalformedParameterizedTypeException jaroslav@56: * if any of the generic superinterfaces refer to a parameterized jaroslav@56: * type that cannot be instantiated for any reason jaroslav@56: * @return an array of interfaces implemented by this class jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public Type[] getGenericInterfaces() { jaroslav@56: if (getGenericSignature() != null) jaroslav@56: return getGenericInfo().getSuperInterfaces(); jaroslav@56: else jaroslav@56: return getInterfaces(); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the {@code Class} representing the component type of an jaroslav@56: * array. If this class does not represent an array class this method jaroslav@56: * returns null. jaroslav@56: * jaroslav@56: * @return the {@code Class} representing the component type of this jaroslav@56: * class if this class is an array jaroslav@56: * @see java.lang.reflect.Array jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public native Class getComponentType(); jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the Java language modifiers for this class or interface, encoded jaroslav@56: * in an integer. The modifiers consist of the Java Virtual Machine's jaroslav@56: * constants for {@code public}, {@code protected}, jaroslav@56: * {@code private}, {@code final}, {@code static}, jaroslav@56: * {@code abstract} and {@code interface}; they should be decoded jaroslav@56: * using the methods of class {@code Modifier}. jaroslav@56: * jaroslav@56: *

If the underlying class is an array class, then its jaroslav@56: * {@code public}, {@code private} and {@code protected} jaroslav@56: * modifiers are the same as those of its component type. If this jaroslav@56: * {@code Class} represents a primitive type or void, its jaroslav@56: * {@code public} modifier is always {@code true}, and its jaroslav@56: * {@code protected} and {@code private} modifiers are always jaroslav@56: * {@code false}. If this object represents an array class, a jaroslav@56: * primitive type or void, then its {@code final} modifier is always jaroslav@56: * {@code true} and its interface modifier is always jaroslav@56: * {@code false}. The values of its other modifiers are not determined jaroslav@56: * by this specification. jaroslav@56: * jaroslav@56: *

The modifier encodings are defined in The Java Virtual Machine jaroslav@56: * Specification, table 4.1. jaroslav@56: * jaroslav@56: * @return the {@code int} representing the modifiers for this class jaroslav@56: * @see java.lang.reflect.Modifier jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public native int getModifiers(); jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Gets the signers of this class. jaroslav@56: * jaroslav@56: * @return the signers of this class, or null if there are no signers. In jaroslav@56: * particular, this method returns null if this object represents jaroslav@56: * a primitive type or void. jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public native Object[] getSigners(); jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Set the signers of this class. jaroslav@56: */ jaroslav@56: native void setSigners(Object[] signers); jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * If this {@code Class} object represents a local or anonymous jaroslav@56: * class within a method, returns a {@link jaroslav@56: * java.lang.reflect.Method Method} object representing the jaroslav@56: * immediately enclosing method of the underlying class. Returns jaroslav@56: * {@code null} otherwise. jaroslav@56: * jaroslav@56: * In particular, this method returns {@code null} if the underlying jaroslav@56: * class is a local or anonymous class immediately enclosed by a type jaroslav@56: * declaration, instance initializer or static initializer. jaroslav@56: * jaroslav@56: * @return the immediately enclosing method of the underlying class, if jaroslav@56: * that class is a local or anonymous class; otherwise {@code null}. jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public Method getEnclosingMethod() { jaroslav@56: EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); jaroslav@56: jaroslav@56: if (enclosingInfo == null) jaroslav@56: return null; jaroslav@56: else { jaroslav@56: if (!enclosingInfo.isMethod()) jaroslav@56: return null; jaroslav@56: jaroslav@56: MethodRepository typeInfo = MethodRepository.make(enclosingInfo.getDescriptor(), jaroslav@56: getFactory()); jaroslav@56: Class returnType = toClass(typeInfo.getReturnType()); jaroslav@56: Type [] parameterTypes = typeInfo.getParameterTypes(); jaroslav@56: Class[] parameterClasses = new Class[parameterTypes.length]; jaroslav@56: jaroslav@56: // Convert Types to Classes; returned types *should* jaroslav@56: // be class objects since the methodDescriptor's used jaroslav@56: // don't have generics information jaroslav@56: for(int i = 0; i < parameterClasses.length; i++) jaroslav@56: parameterClasses[i] = toClass(parameterTypes[i]); jaroslav@56: jaroslav@56: /* jaroslav@56: * Loop over all declared methods; match method name, jaroslav@56: * number of and type of parameters, *and* return jaroslav@56: * type. Matching return type is also necessary jaroslav@56: * because of covariant returns, etc. jaroslav@56: */ jaroslav@56: for(Method m: enclosingInfo.getEnclosingClass().getDeclaredMethods()) { jaroslav@56: if (m.getName().equals(enclosingInfo.getName()) ) { jaroslav@56: Class[] candidateParamClasses = m.getParameterTypes(); jaroslav@56: if (candidateParamClasses.length == parameterClasses.length) { jaroslav@56: boolean matches = true; jaroslav@56: for(int i = 0; i < candidateParamClasses.length; i++) { jaroslav@56: if (!candidateParamClasses[i].equals(parameterClasses[i])) { jaroslav@56: matches = false; jaroslav@56: break; jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: if (matches) { // finally, check return type jaroslav@56: if (m.getReturnType().equals(returnType) ) jaroslav@56: return m; jaroslav@56: } jaroslav@56: } jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: throw new InternalError("Enclosing method not found"); jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: private native Object[] getEnclosingMethod0(); jaroslav@56: jaroslav@56: private EnclosingMethodInfo getEnclosingMethodInfo() { jaroslav@56: Object[] enclosingInfo = getEnclosingMethod0(); jaroslav@56: if (enclosingInfo == null) jaroslav@56: return null; jaroslav@56: else { jaroslav@56: return new EnclosingMethodInfo(enclosingInfo); jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: private final static class EnclosingMethodInfo { jaroslav@56: private Class enclosingClass; jaroslav@56: private String name; jaroslav@56: private String descriptor; jaroslav@56: jaroslav@56: private EnclosingMethodInfo(Object[] enclosingInfo) { jaroslav@56: if (enclosingInfo.length != 3) jaroslav@56: throw new InternalError("Malformed enclosing method information"); jaroslav@56: try { jaroslav@56: // The array is expected to have three elements: jaroslav@56: jaroslav@56: // the immediately enclosing class jaroslav@56: enclosingClass = (Class) enclosingInfo[0]; jaroslav@56: assert(enclosingClass != null); jaroslav@56: jaroslav@56: // the immediately enclosing method or constructor's jaroslav@56: // name (can be null). jaroslav@56: name = (String) enclosingInfo[1]; jaroslav@56: jaroslav@56: // the immediately enclosing method or constructor's jaroslav@56: // descriptor (null iff name is). jaroslav@56: descriptor = (String) enclosingInfo[2]; jaroslav@56: assert((name != null && descriptor != null) || name == descriptor); jaroslav@56: } catch (ClassCastException cce) { jaroslav@56: throw new InternalError("Invalid type in enclosing method information"); jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: boolean isPartial() { jaroslav@56: return enclosingClass == null || name == null || descriptor == null; jaroslav@56: } jaroslav@56: jaroslav@56: boolean isConstructor() { return !isPartial() && "".equals(name); } jaroslav@56: jaroslav@56: boolean isMethod() { return !isPartial() && !isConstructor() && !"".equals(name); } jaroslav@56: jaroslav@56: Class getEnclosingClass() { return enclosingClass; } jaroslav@56: jaroslav@56: String getName() { return name; } jaroslav@56: jaroslav@56: String getDescriptor() { return descriptor; } jaroslav@56: jaroslav@56: } jaroslav@56: jaroslav@56: private static Class toClass(Type o) { jaroslav@56: if (o instanceof GenericArrayType) jaroslav@56: return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()), jaroslav@56: 0) jaroslav@56: .getClass(); jaroslav@56: return (Class)o; jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * If this {@code Class} object represents a local or anonymous jaroslav@56: * class within a constructor, returns a {@link jaroslav@56: * java.lang.reflect.Constructor Constructor} object representing jaroslav@56: * the immediately enclosing constructor of the underlying jaroslav@56: * class. Returns {@code null} otherwise. In particular, this jaroslav@56: * method returns {@code null} if the underlying class is a local jaroslav@56: * or anonymous class immediately enclosed by a type declaration, jaroslav@56: * instance initializer or static initializer. jaroslav@56: * jaroslav@56: * @return the immediately enclosing constructor of the underlying class, if jaroslav@56: * that class is a local or anonymous class; otherwise {@code null}. jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public Constructor getEnclosingConstructor() { jaroslav@56: EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); jaroslav@56: jaroslav@56: if (enclosingInfo == null) jaroslav@56: return null; jaroslav@56: else { jaroslav@56: if (!enclosingInfo.isConstructor()) jaroslav@56: return null; jaroslav@56: jaroslav@56: ConstructorRepository typeInfo = ConstructorRepository.make(enclosingInfo.getDescriptor(), jaroslav@56: getFactory()); jaroslav@56: Type [] parameterTypes = typeInfo.getParameterTypes(); jaroslav@56: Class[] parameterClasses = new Class[parameterTypes.length]; jaroslav@56: jaroslav@56: // Convert Types to Classes; returned types *should* jaroslav@56: // be class objects since the methodDescriptor's used jaroslav@56: // don't have generics information jaroslav@56: for(int i = 0; i < parameterClasses.length; i++) jaroslav@56: parameterClasses[i] = toClass(parameterTypes[i]); jaroslav@56: jaroslav@56: /* jaroslav@56: * Loop over all declared constructors; match number jaroslav@56: * of and type of parameters. jaroslav@56: */ jaroslav@56: for(Constructor c: enclosingInfo.getEnclosingClass().getDeclaredConstructors()) { jaroslav@56: Class[] candidateParamClasses = c.getParameterTypes(); jaroslav@56: if (candidateParamClasses.length == parameterClasses.length) { jaroslav@56: boolean matches = true; jaroslav@56: for(int i = 0; i < candidateParamClasses.length; i++) { jaroslav@56: if (!candidateParamClasses[i].equals(parameterClasses[i])) { jaroslav@56: matches = false; jaroslav@56: break; jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: if (matches) jaroslav@56: return c; jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: throw new InternalError("Enclosing constructor not found"); jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * If the class or interface represented by this {@code Class} object jaroslav@56: * is a member of another class, returns the {@code Class} object jaroslav@56: * representing the class in which it was declared. This method returns jaroslav@56: * null if this class or interface is not a member of any other class. If jaroslav@56: * this {@code Class} object represents an array class, a primitive jaroslav@56: * type, or void,then this method returns null. jaroslav@56: * jaroslav@56: * @return the declaring class for this class jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public native Class getDeclaringClass(); jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the immediately enclosing class of the underlying jaroslav@56: * class. If the underlying class is a top level class this jaroslav@56: * method returns {@code null}. jaroslav@56: * @return the immediately enclosing class of the underlying class jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public Class getEnclosingClass() { jaroslav@56: // There are five kinds of classes (or interfaces): jaroslav@56: // a) Top level classes jaroslav@56: // b) Nested classes (static member classes) jaroslav@56: // c) Inner classes (non-static member classes) jaroslav@56: // d) Local classes (named classes declared within a method) jaroslav@56: // e) Anonymous classes jaroslav@56: jaroslav@56: jaroslav@56: // JVM Spec 4.8.6: A class must have an EnclosingMethod jaroslav@56: // attribute if and only if it is a local class or an jaroslav@56: // anonymous class. jaroslav@56: EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); jaroslav@56: jaroslav@56: if (enclosingInfo == null) { jaroslav@56: // This is a top level or a nested class or an inner class (a, b, or c) jaroslav@56: return getDeclaringClass(); jaroslav@56: } else { jaroslav@56: Class enclosingClass = enclosingInfo.getEnclosingClass(); jaroslav@56: // This is a local class or an anonymous class (d or e) jaroslav@56: if (enclosingClass == this || enclosingClass == null) jaroslav@56: throw new InternalError("Malformed enclosing method information"); jaroslav@56: else jaroslav@56: return enclosingClass; jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the simple name of the underlying class as given in the jaroslav@56: * source code. Returns an empty string if the underlying class is jaroslav@56: * anonymous. jaroslav@56: * jaroslav@56: *

The simple name of an array is the simple name of the jaroslav@56: * component type with "[]" appended. In particular the simple jaroslav@56: * name of an array whose component type is anonymous is "[]". jaroslav@56: * jaroslav@56: * @return the simple name of the underlying class jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public String getSimpleName() { jaroslav@56: if (isArray()) jaroslav@56: return getComponentType().getSimpleName()+"[]"; jaroslav@56: jaroslav@56: String simpleName = getSimpleBinaryName(); jaroslav@56: if (simpleName == null) { // top level class jaroslav@56: simpleName = getName(); jaroslav@56: return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name jaroslav@56: } jaroslav@56: // According to JLS3 "Binary Compatibility" (13.1) the binary jaroslav@56: // name of non-package classes (not top level) is the binary jaroslav@56: // name of the immediately enclosing class followed by a '$' followed by: jaroslav@56: // (for nested and inner classes): the simple name. jaroslav@56: // (for local classes): 1 or more digits followed by the simple name. jaroslav@56: // (for anonymous classes): 1 or more digits. jaroslav@56: jaroslav@56: // Since getSimpleBinaryName() will strip the binary name of jaroslav@56: // the immediatly enclosing class, we are now looking at a jaroslav@56: // string that matches the regular expression "\$[0-9]*" jaroslav@56: // followed by a simple name (considering the simple of an jaroslav@56: // anonymous class to be the empty string). jaroslav@56: jaroslav@56: // Remove leading "\$[0-9]*" from the name jaroslav@56: int length = simpleName.length(); jaroslav@56: if (length < 1 || simpleName.charAt(0) != '$') jaroslav@56: throw new InternalError("Malformed class name"); jaroslav@56: int index = 1; jaroslav@56: while (index < length && isAsciiDigit(simpleName.charAt(index))) jaroslav@56: index++; jaroslav@56: // Eventually, this is the empty string iff this is an anonymous class jaroslav@56: return simpleName.substring(index); jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Character.isDigit answers {@code true} to some non-ascii jaroslav@56: * digits. This one does not. jaroslav@56: */ jaroslav@56: private static boolean isAsciiDigit(char c) { jaroslav@56: return '0' <= c && c <= '9'; jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the canonical name of the underlying class as jaroslav@56: * defined by the Java Language Specification. Returns null if jaroslav@56: * the underlying class does not have a canonical name (i.e., if jaroslav@56: * it is a local or anonymous class or an array whose component jaroslav@56: * type does not have a canonical name). jaroslav@56: * @return the canonical name of the underlying class if it exists, and jaroslav@56: * {@code null} otherwise. jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public String getCanonicalName() { jaroslav@56: if (isArray()) { jaroslav@56: String canonicalName = getComponentType().getCanonicalName(); jaroslav@56: if (canonicalName != null) jaroslav@56: return canonicalName + "[]"; jaroslav@56: else jaroslav@56: return null; jaroslav@56: } jaroslav@56: if (isLocalOrAnonymousClass()) jaroslav@56: return null; jaroslav@56: Class enclosingClass = getEnclosingClass(); jaroslav@56: if (enclosingClass == null) { // top level class jaroslav@56: return getName(); jaroslav@56: } else { jaroslav@56: String enclosingName = enclosingClass.getCanonicalName(); jaroslav@56: if (enclosingName == null) jaroslav@56: return null; jaroslav@56: return enclosingName + "." + getSimpleName(); jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns {@code true} if and only if the underlying class jaroslav@56: * is an anonymous class. jaroslav@56: * jaroslav@56: * @return {@code true} if and only if this class is an anonymous class. jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public boolean isAnonymousClass() { jaroslav@56: return "".equals(getSimpleName()); jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns {@code true} if and only if the underlying class jaroslav@56: * is a local class. jaroslav@56: * jaroslav@56: * @return {@code true} if and only if this class is a local class. jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public boolean isLocalClass() { jaroslav@56: return isLocalOrAnonymousClass() && !isAnonymousClass(); jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns {@code true} if and only if the underlying class jaroslav@56: * is a member class. jaroslav@56: * jaroslav@56: * @return {@code true} if and only if this class is a member class. jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public boolean isMemberClass() { jaroslav@56: return getSimpleBinaryName() != null && !isLocalOrAnonymousClass(); jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the "simple binary name" of the underlying class, i.e., jaroslav@56: * the binary name without the leading enclosing class name. jaroslav@56: * Returns {@code null} if the underlying class is a top level jaroslav@56: * class. jaroslav@56: */ jaroslav@56: private String getSimpleBinaryName() { jaroslav@56: Class enclosingClass = getEnclosingClass(); jaroslav@56: if (enclosingClass == null) // top level class jaroslav@56: return null; jaroslav@56: // Otherwise, strip the enclosing class' name jaroslav@56: try { jaroslav@56: return getName().substring(enclosingClass.getName().length()); jaroslav@56: } catch (IndexOutOfBoundsException ex) { jaroslav@56: throw new InternalError("Malformed class name"); jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns {@code true} if this is a local class or an anonymous jaroslav@56: * class. Returns {@code false} otherwise. jaroslav@56: */ jaroslav@56: private boolean isLocalOrAnonymousClass() { jaroslav@56: // JVM Spec 4.8.6: A class must have an EnclosingMethod jaroslav@56: // attribute if and only if it is a local class or an jaroslav@56: // anonymous class. jaroslav@56: return getEnclosingMethodInfo() != null; jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns an array containing {@code Class} objects representing all jaroslav@56: * the public classes and interfaces that are members of the class jaroslav@56: * represented by this {@code Class} object. This includes public jaroslav@56: * class and interface members inherited from superclasses and public class jaroslav@56: * and interface members declared by the class. This method returns an jaroslav@56: * array of length 0 if this {@code Class} object has no public member jaroslav@56: * classes or interfaces. This method also returns an array of length 0 if jaroslav@56: * this {@code Class} object represents a primitive type, an array jaroslav@56: * class, or void. jaroslav@56: * jaroslav@56: * @return the array of {@code Class} objects representing the public jaroslav@56: * members of this class jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *

    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.PUBLIC)} method jaroslav@56: * denies access to the classes within this class jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Class[] getClasses() { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); jaroslav@56: jaroslav@56: // Privileged so this implementation can look at DECLARED classes, jaroslav@56: // something the caller might not have privilege to do. The code here jaroslav@56: // is allowed to look at DECLARED classes because (1) it does not hand jaroslav@56: // out anything other than public members and (2) public member access jaroslav@56: // has already been ok'd by the SecurityManager. jaroslav@56: jaroslav@56: return java.security.AccessController.doPrivileged( jaroslav@56: new java.security.PrivilegedAction[]>() { jaroslav@56: public Class[] run() { jaroslav@56: List> list = new ArrayList<>(); jaroslav@56: Class currentClass = Class.this; jaroslav@56: while (currentClass != null) { jaroslav@56: Class[] members = currentClass.getDeclaredClasses(); jaroslav@56: for (int i = 0; i < members.length; i++) { jaroslav@56: if (Modifier.isPublic(members[i].getModifiers())) { jaroslav@56: list.add(members[i]); jaroslav@56: } jaroslav@56: } jaroslav@56: currentClass = currentClass.getSuperclass(); jaroslav@56: } jaroslav@56: return list.toArray(new Class[0]); jaroslav@56: } jaroslav@56: }); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns an array containing {@code Field} objects reflecting all jaroslav@56: * the accessible public fields of the class or interface represented by jaroslav@56: * this {@code Class} object. The elements in the array returned are jaroslav@56: * not sorted and are not in any particular order. This method returns an jaroslav@56: * array of length 0 if the class or interface has no accessible public jaroslav@56: * fields, or if it represents an array class, a primitive type, or void. jaroslav@56: * jaroslav@56: *

Specifically, if this {@code Class} object represents a class, jaroslav@56: * this method returns the public fields of this class and of all its jaroslav@56: * superclasses. If this {@code Class} object represents an jaroslav@56: * interface, this method returns the fields of this interface and of all jaroslav@56: * its superinterfaces. jaroslav@56: * jaroslav@56: *

The implicit length field for array class is not reflected by this jaroslav@56: * method. User code should use the methods of class {@code Array} to jaroslav@56: * manipulate arrays. jaroslav@56: * jaroslav@56: *

See The Java Language Specification, sections 8.2 and 8.3. jaroslav@56: * jaroslav@56: * @return the array of {@code Field} objects representing the jaroslav@56: * public fields jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *

    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.PUBLIC)} denies jaroslav@56: * access to the fields within this class jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Field[] getFields() throws SecurityException { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); jaroslav@56: return copyFields(privateGetPublicFields(null)); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns an array containing {@code Method} objects reflecting all jaroslav@56: * the public member methods of the class or interface represented jaroslav@56: * by this {@code Class} object, including those declared by the class jaroslav@56: * or interface and those inherited from superclasses and jaroslav@56: * superinterfaces. Array classes return all the (public) member methods jaroslav@56: * inherited from the {@code Object} class. The elements in the array jaroslav@56: * returned are not sorted and are not in any particular order. This jaroslav@56: * method returns an array of length 0 if this {@code Class} object jaroslav@56: * represents a class or interface that has no public member methods, or if jaroslav@56: * this {@code Class} object represents a primitive type or void. jaroslav@56: * jaroslav@56: *

The class initialization method {@code } is not jaroslav@56: * included in the returned array. If the class declares multiple public jaroslav@56: * member methods with the same parameter types, they are all included in jaroslav@56: * the returned array. jaroslav@56: * jaroslav@56: *

See The Java Language Specification, sections 8.2 and 8.4. jaroslav@56: * jaroslav@56: * @return the array of {@code Method} objects representing the jaroslav@56: * public methods of this class jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *

    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.PUBLIC)} denies jaroslav@56: * access to the methods within this class jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Method[] getMethods() throws SecurityException { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); jaroslav@56: return copyMethods(privateGetPublicMethods()); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns an array containing {@code Constructor} objects reflecting jaroslav@56: * all the public constructors of the class represented by this jaroslav@56: * {@code Class} object. An array of length 0 is returned if the jaroslav@56: * class has no public constructors, or if the class is an array class, or jaroslav@56: * if the class reflects a primitive type or void. jaroslav@56: * jaroslav@56: * Note that while this method returns an array of {@code jaroslav@56: * Constructor} objects (that is an array of constructors from jaroslav@56: * this class), the return type of this method is {@code jaroslav@56: * Constructor[]} and not {@code Constructor[]} as jaroslav@56: * might be expected. This less informative return type is jaroslav@56: * necessary since after being returned from this method, the jaroslav@56: * array could be modified to hold {@code Constructor} objects for jaroslav@56: * different classes, which would violate the type guarantees of jaroslav@56: * {@code Constructor[]}. jaroslav@56: * jaroslav@56: * @return the array of {@code Constructor} objects representing the jaroslav@56: * public constructors of this class jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *
    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.PUBLIC)} denies jaroslav@56: * access to the constructors within this class jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Constructor[] getConstructors() throws SecurityException { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); jaroslav@56: return copyConstructors(privateGetDeclaredConstructors(true)); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns a {@code Field} object that reflects the specified public jaroslav@56: * member field of the class or interface represented by this jaroslav@56: * {@code Class} object. The {@code name} parameter is a jaroslav@56: * {@code String} specifying the simple name of the desired field. jaroslav@56: * jaroslav@56: *

The field to be reflected is determined by the algorithm that jaroslav@56: * follows. Let C be the class represented by this object: jaroslav@56: *

    jaroslav@56: *
  1. If C declares a public field with the name specified, that is the jaroslav@56: * field to be reflected.
  2. jaroslav@56: *
  3. If no field was found in step 1 above, this algorithm is applied jaroslav@56: * recursively to each direct superinterface of C. The direct jaroslav@56: * superinterfaces are searched in the order they were declared.
  4. jaroslav@56: *
  5. If no field was found in steps 1 and 2 above, and C has a jaroslav@56: * superclass S, then this algorithm is invoked recursively upon S. jaroslav@56: * If C has no superclass, then a {@code NoSuchFieldException} jaroslav@56: * is thrown.
  6. jaroslav@56: *
jaroslav@56: * jaroslav@56: *

See The Java Language Specification, sections 8.2 and 8.3. jaroslav@56: * jaroslav@56: * @param name the field name jaroslav@56: * @return the {@code Field} object of this class specified by jaroslav@56: * {@code name} jaroslav@56: * @exception NoSuchFieldException if a field with the specified name is jaroslav@56: * not found. jaroslav@56: * @exception NullPointerException if {@code name} is {@code null} jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *

    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.PUBLIC)} denies jaroslav@56: * access to the field jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Field getField(String name) jaroslav@56: throws NoSuchFieldException, SecurityException { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); jaroslav@56: Field field = getField0(name); jaroslav@56: if (field == null) { jaroslav@56: throw new NoSuchFieldException(name); jaroslav@56: } jaroslav@56: return field; jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns a {@code Method} object that reflects the specified public jaroslav@56: * member method of the class or interface represented by this jaroslav@56: * {@code Class} object. The {@code name} parameter is a jaroslav@56: * {@code String} specifying the simple name of the desired method. The jaroslav@56: * {@code parameterTypes} parameter is an array of {@code Class} jaroslav@56: * objects that identify the method's formal parameter types, in declared jaroslav@56: * order. If {@code parameterTypes} is {@code null}, it is jaroslav@56: * treated as if it were an empty array. jaroslav@56: * jaroslav@56: *

If the {@code name} is "{@code };"or "{@code }" a jaroslav@56: * {@code NoSuchMethodException} is raised. Otherwise, the method to jaroslav@56: * be reflected is determined by the algorithm that follows. Let C be the jaroslav@56: * class represented by this object: jaroslav@56: *

    jaroslav@56: *
  1. C is searched for any matching methods. If no matching jaroslav@56: * method is found, the algorithm of step 1 is invoked recursively on jaroslav@56: * the superclass of C.
  2. jaroslav@56: *
  3. If no method was found in step 1 above, the superinterfaces of C jaroslav@56: * are searched for a matching method. If any such method is found, it jaroslav@56: * is reflected.
  4. jaroslav@56: *
jaroslav@56: * jaroslav@56: * To find a matching method in a class C:  If C declares exactly one jaroslav@56: * public method with the specified name and exactly the same formal jaroslav@56: * parameter types, that is the method reflected. If more than one such jaroslav@56: * method is found in C, and one of these methods has a return type that is jaroslav@56: * more specific than any of the others, that method is reflected; jaroslav@56: * otherwise one of the methods is chosen arbitrarily. jaroslav@56: * jaroslav@56: *

Note that there may be more than one matching method in a jaroslav@56: * class because while the Java language forbids a class to jaroslav@56: * declare multiple methods with the same signature but different jaroslav@56: * return types, the Java virtual machine does not. This jaroslav@56: * increased flexibility in the virtual machine can be used to jaroslav@56: * implement various language features. For example, covariant jaroslav@56: * returns can be implemented with {@linkplain jaroslav@56: * java.lang.reflect.Method#isBridge bridge methods}; the bridge jaroslav@56: * method and the method being overridden would have the same jaroslav@56: * signature but different return types. jaroslav@56: * jaroslav@56: *

See The Java Language Specification, sections 8.2 and 8.4. jaroslav@56: * jaroslav@56: * @param name the name of the method jaroslav@56: * @param parameterTypes the list of parameters jaroslav@56: * @return the {@code Method} object that matches the specified jaroslav@56: * {@code name} and {@code parameterTypes} jaroslav@56: * @exception NoSuchMethodException if a matching method is not found jaroslav@56: * or if the name is "<init>"or "<clinit>". jaroslav@56: * @exception NullPointerException if {@code name} is {@code null} jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *

    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.PUBLIC)} denies jaroslav@56: * access to the method jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Method getMethod(String name, Class... parameterTypes) jaroslav@56: throws NoSuchMethodException, SecurityException { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); jaroslav@56: Method method = getMethod0(name, parameterTypes); jaroslav@56: if (method == null) { jaroslav@56: throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); jaroslav@56: } jaroslav@56: return method; jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns a {@code Constructor} object that reflects the specified jaroslav@56: * public constructor of the class represented by this {@code Class} jaroslav@56: * object. The {@code parameterTypes} parameter is an array of jaroslav@56: * {@code Class} objects that identify the constructor's formal jaroslav@56: * parameter types, in declared order. jaroslav@56: * jaroslav@56: * If this {@code Class} object represents an inner class jaroslav@56: * declared in a non-static context, the formal parameter types jaroslav@56: * include the explicit enclosing instance as the first parameter. jaroslav@56: * jaroslav@56: *

The constructor to reflect is the public constructor of the class jaroslav@56: * represented by this {@code Class} object whose formal parameter jaroslav@56: * types match those specified by {@code parameterTypes}. jaroslav@56: * jaroslav@56: * @param parameterTypes the parameter array jaroslav@56: * @return the {@code Constructor} object of the public constructor that jaroslav@56: * matches the specified {@code parameterTypes} jaroslav@56: * @exception NoSuchMethodException if a matching method is not found. jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *

    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.PUBLIC)} denies jaroslav@56: * access to the constructor jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Constructor getConstructor(Class... parameterTypes) jaroslav@56: throws NoSuchMethodException, SecurityException { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); jaroslav@56: return getConstructor0(parameterTypes, Member.PUBLIC); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns an array of {@code Class} objects reflecting all the jaroslav@56: * classes and interfaces declared as members of the class represented by jaroslav@56: * this {@code Class} object. This includes public, protected, default jaroslav@56: * (package) access, and private classes and interfaces declared by the jaroslav@56: * class, but excludes inherited classes and interfaces. This method jaroslav@56: * returns an array of length 0 if the class declares no classes or jaroslav@56: * interfaces as members, or if this {@code Class} object represents a jaroslav@56: * primitive type, an array class, or void. jaroslav@56: * jaroslav@56: * @return the array of {@code Class} objects representing all the jaroslav@56: * declared members of this class jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *
    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.DECLARED)} denies jaroslav@56: * access to the declared classes within this class jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Class[] getDeclaredClasses() throws SecurityException { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); jaroslav@56: return getDeclaredClasses0(); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns an array of {@code Field} objects reflecting all the fields jaroslav@56: * declared by the class or interface represented by this jaroslav@56: * {@code Class} object. This includes public, protected, default jaroslav@56: * (package) access, and private fields, but excludes inherited fields. jaroslav@56: * The elements in the array returned are not sorted and are not in any jaroslav@56: * particular order. This method returns an array of length 0 if the class jaroslav@56: * or interface declares no fields, or if this {@code Class} object jaroslav@56: * represents a primitive type, an array class, or void. jaroslav@56: * jaroslav@56: *

See The Java Language Specification, sections 8.2 and 8.3. jaroslav@56: * jaroslav@56: * @return the array of {@code Field} objects representing all the jaroslav@56: * declared fields of this class jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *

    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.DECLARED)} denies jaroslav@56: * access to the declared fields within this class jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Field[] getDeclaredFields() throws SecurityException { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); jaroslav@56: return copyFields(privateGetDeclaredFields(false)); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns an array of {@code Method} objects reflecting all the jaroslav@56: * methods declared by the class or interface represented by this jaroslav@56: * {@code Class} object. This includes public, protected, default jaroslav@56: * (package) access, and private methods, but excludes inherited methods. jaroslav@56: * The elements in the array returned are not sorted and are not in any jaroslav@56: * particular order. This method returns an array of length 0 if the class jaroslav@56: * or interface declares no methods, or if this {@code Class} object jaroslav@56: * represents a primitive type, an array class, or void. The class jaroslav@56: * initialization method {@code } is not included in the jaroslav@56: * returned array. If the class declares multiple public member methods jaroslav@56: * with the same parameter types, they are all included in the returned jaroslav@56: * array. jaroslav@56: * jaroslav@56: *

See The Java Language Specification, section 8.2. jaroslav@56: * jaroslav@56: * @return the array of {@code Method} objects representing all the jaroslav@56: * declared methods of this class jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *

    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.DECLARED)} denies jaroslav@56: * access to the declared methods within this class jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Method[] getDeclaredMethods() throws SecurityException { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); jaroslav@56: return copyMethods(privateGetDeclaredMethods(false)); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns an array of {@code Constructor} objects reflecting all the jaroslav@56: * constructors declared by the class represented by this jaroslav@56: * {@code Class} object. These are public, protected, default jaroslav@56: * (package) access, and private constructors. The elements in the array jaroslav@56: * returned are not sorted and are not in any particular order. If the jaroslav@56: * class has a default constructor, it is included in the returned array. jaroslav@56: * This method returns an array of length 0 if this {@code Class} jaroslav@56: * object represents an interface, a primitive type, an array class, or jaroslav@56: * void. jaroslav@56: * jaroslav@56: *

See The Java Language Specification, section 8.2. jaroslav@56: * jaroslav@56: * @return the array of {@code Constructor} objects representing all the jaroslav@56: * declared constructors of this class jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *

    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.DECLARED)} denies jaroslav@56: * access to the declared constructors within this class jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Constructor[] getDeclaredConstructors() throws SecurityException { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); jaroslav@56: return copyConstructors(privateGetDeclaredConstructors(false)); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns a {@code Field} object that reflects the specified declared jaroslav@56: * field of the class or interface represented by this {@code Class} jaroslav@56: * object. The {@code name} parameter is a {@code String} that jaroslav@56: * specifies the simple name of the desired field. Note that this method jaroslav@56: * will not reflect the {@code length} field of an array class. jaroslav@56: * jaroslav@56: * @param name the name of the field jaroslav@56: * @return the {@code Field} object for the specified field in this jaroslav@56: * class jaroslav@56: * @exception NoSuchFieldException if a field with the specified name is jaroslav@56: * not found. jaroslav@56: * @exception NullPointerException if {@code name} is {@code null} jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *
    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.DECLARED)} denies jaroslav@56: * access to the declared field jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Field getDeclaredField(String name) jaroslav@56: throws NoSuchFieldException, SecurityException { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); jaroslav@56: Field field = searchFields(privateGetDeclaredFields(false), name); jaroslav@56: if (field == null) { jaroslav@56: throw new NoSuchFieldException(name); jaroslav@56: } jaroslav@56: return field; jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns a {@code Method} object that reflects the specified jaroslav@56: * declared method of the class or interface represented by this jaroslav@56: * {@code Class} object. The {@code name} parameter is a jaroslav@56: * {@code String} that specifies the simple name of the desired jaroslav@56: * method, and the {@code parameterTypes} parameter is an array of jaroslav@56: * {@code Class} objects that identify the method's formal parameter jaroslav@56: * types, in declared order. If more than one method with the same jaroslav@56: * parameter types is declared in a class, and one of these methods has a jaroslav@56: * return type that is more specific than any of the others, that method is jaroslav@56: * returned; otherwise one of the methods is chosen arbitrarily. If the jaroslav@56: * name is "<init>"or "<clinit>" a {@code NoSuchMethodException} jaroslav@56: * is raised. jaroslav@56: * jaroslav@56: * @param name the name of the method jaroslav@56: * @param parameterTypes the parameter array jaroslav@56: * @return the {@code Method} object for the method of this class jaroslav@56: * matching the specified name and parameters jaroslav@56: * @exception NoSuchMethodException if a matching method is not found. jaroslav@56: * @exception NullPointerException if {@code name} is {@code null} jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *
    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.DECLARED)} denies jaroslav@56: * access to the declared method jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Method getDeclaredMethod(String name, Class... parameterTypes) jaroslav@56: throws NoSuchMethodException, SecurityException { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); jaroslav@56: Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); jaroslav@56: if (method == null) { jaroslav@56: throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); jaroslav@56: } jaroslav@56: return method; jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns a {@code Constructor} object that reflects the specified jaroslav@56: * constructor of the class or interface represented by this jaroslav@56: * {@code Class} object. The {@code parameterTypes} parameter is jaroslav@56: * an array of {@code Class} objects that identify the constructor's jaroslav@56: * formal parameter types, in declared order. jaroslav@56: * jaroslav@56: * If this {@code Class} object represents an inner class jaroslav@56: * declared in a non-static context, the formal parameter types jaroslav@56: * include the explicit enclosing instance as the first parameter. jaroslav@56: * jaroslav@56: * @param parameterTypes the parameter array jaroslav@56: * @return The {@code Constructor} object for the constructor with the jaroslav@56: * specified parameter list jaroslav@56: * @exception NoSuchMethodException if a matching method is not found. jaroslav@56: * @exception SecurityException jaroslav@56: * If a security manager, s, is present and any of the jaroslav@56: * following conditions is met: jaroslav@56: * jaroslav@56: *
    jaroslav@56: * jaroslav@56: *
  • invocation of jaroslav@56: * {@link SecurityManager#checkMemberAccess jaroslav@56: * s.checkMemberAccess(this, Member.DECLARED)} denies jaroslav@56: * access to the declared constructor jaroslav@56: * jaroslav@56: *
  • the caller's class loader is not the same as or an jaroslav@56: * ancestor of the class loader for the current class and jaroslav@56: * invocation of {@link SecurityManager#checkPackageAccess jaroslav@56: * s.checkPackageAccess()} denies access to the package jaroslav@56: * of this class jaroslav@56: * jaroslav@56: *
jaroslav@56: * jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public Constructor getDeclaredConstructor(Class... parameterTypes) jaroslav@56: throws NoSuchMethodException, SecurityException { jaroslav@56: // be very careful not to change the stack depth of this jaroslav@56: // checkMemberAccess call for security reasons jaroslav@56: // see java.lang.SecurityManager.checkMemberAccess jaroslav@56: checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); jaroslav@56: return getConstructor0(parameterTypes, Member.DECLARED); jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Finds a resource with a given name. The rules for searching resources jaroslav@56: * associated with a given class are implemented by the defining jaroslav@56: * {@linkplain ClassLoader class loader} of the class. This method jaroslav@56: * delegates to this object's class loader. If this object was loaded by jaroslav@56: * the bootstrap class loader, the method delegates to {@link jaroslav@56: * ClassLoader#getSystemResourceAsStream}. jaroslav@56: * jaroslav@56: *

Before delegation, an absolute resource name is constructed from the jaroslav@56: * given resource name using this algorithm: jaroslav@56: * jaroslav@56: *

    jaroslav@56: * jaroslav@56: *
  • If the {@code name} begins with a {@code '/'} jaroslav@56: * ('\u002f'), then the absolute name of the resource is the jaroslav@56: * portion of the {@code name} following the {@code '/'}. jaroslav@56: * jaroslav@56: *
  • Otherwise, the absolute name is of the following form: jaroslav@56: * jaroslav@56: *
    jaroslav@56: * {@code modified_package_name/name} jaroslav@56: *
    jaroslav@56: * jaroslav@56: *

    Where the {@code modified_package_name} is the package name of this jaroslav@56: * object with {@code '/'} substituted for {@code '.'} jaroslav@56: * ('\u002e'). jaroslav@56: * jaroslav@56: *

jaroslav@56: * jaroslav@56: * @param name name of the desired resource jaroslav@56: * @return A {@link java.io.InputStream} object or {@code null} if jaroslav@56: * no resource with this name is found jaroslav@56: * @throws NullPointerException If {@code name} is {@code null} jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public InputStream getResourceAsStream(String name) { jaroslav@56: name = resolveName(name); jaroslav@56: ClassLoader cl = getClassLoader0(); jaroslav@56: if (cl==null) { jaroslav@56: // A system class. jaroslav@56: return ClassLoader.getSystemResourceAsStream(name); jaroslav@56: } jaroslav@56: return cl.getResourceAsStream(name); jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Finds a resource with a given name. The rules for searching resources jaroslav@56: * associated with a given class are implemented by the defining jaroslav@56: * {@linkplain ClassLoader class loader} of the class. This method jaroslav@56: * delegates to this object's class loader. If this object was loaded by jaroslav@56: * the bootstrap class loader, the method delegates to {@link jaroslav@56: * ClassLoader#getSystemResource}. jaroslav@56: * jaroslav@56: *

Before delegation, an absolute resource name is constructed from the jaroslav@56: * given resource name using this algorithm: jaroslav@56: * jaroslav@56: *

    jaroslav@56: * jaroslav@56: *
  • If the {@code name} begins with a {@code '/'} jaroslav@56: * ('\u002f'), then the absolute name of the resource is the jaroslav@56: * portion of the {@code name} following the {@code '/'}. jaroslav@56: * jaroslav@56: *
  • Otherwise, the absolute name is of the following form: jaroslav@56: * jaroslav@56: *
    jaroslav@56: * {@code modified_package_name/name} jaroslav@56: *
    jaroslav@56: * jaroslav@56: *

    Where the {@code modified_package_name} is the package name of this jaroslav@56: * object with {@code '/'} substituted for {@code '.'} jaroslav@56: * ('\u002e'). jaroslav@56: * jaroslav@56: *

jaroslav@56: * jaroslav@56: * @param name name of the desired resource jaroslav@56: * @return A {@link java.net.URL} object or {@code null} if no jaroslav@56: * resource with this name is found jaroslav@56: * @since JDK1.1 jaroslav@56: */ jaroslav@56: public java.net.URL getResource(String name) { jaroslav@56: name = resolveName(name); jaroslav@56: ClassLoader cl = getClassLoader0(); jaroslav@56: if (cl==null) { jaroslav@56: // A system class. jaroslav@56: return ClassLoader.getSystemResource(name); jaroslav@56: } jaroslav@56: return cl.getResource(name); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: jaroslav@56: /** protection domain returned when the internal domain is null */ jaroslav@56: private static java.security.ProtectionDomain allPermDomain; jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the {@code ProtectionDomain} of this class. If there is a jaroslav@56: * security manager installed, this method first calls the security jaroslav@56: * manager's {@code checkPermission} method with a jaroslav@56: * {@code RuntimePermission("getProtectionDomain")} permission to jaroslav@56: * ensure it's ok to get the jaroslav@56: * {@code ProtectionDomain}. jaroslav@56: * jaroslav@56: * @return the ProtectionDomain of this class jaroslav@56: * jaroslav@56: * @throws SecurityException jaroslav@56: * if a security manager exists and its jaroslav@56: * {@code checkPermission} method doesn't allow jaroslav@56: * getting the ProtectionDomain. jaroslav@56: * jaroslav@56: * @see java.security.ProtectionDomain jaroslav@56: * @see SecurityManager#checkPermission jaroslav@56: * @see java.lang.RuntimePermission jaroslav@56: * @since 1.2 jaroslav@56: */ jaroslav@56: public java.security.ProtectionDomain getProtectionDomain() { jaroslav@56: SecurityManager sm = System.getSecurityManager(); jaroslav@56: if (sm != null) { jaroslav@56: sm.checkPermission(SecurityConstants.GET_PD_PERMISSION); jaroslav@56: } jaroslav@56: java.security.ProtectionDomain pd = getProtectionDomain0(); jaroslav@56: if (pd == null) { jaroslav@56: if (allPermDomain == null) { jaroslav@56: java.security.Permissions perms = jaroslav@56: new java.security.Permissions(); jaroslav@56: perms.add(SecurityConstants.ALL_PERMISSION); jaroslav@56: allPermDomain = jaroslav@56: new java.security.ProtectionDomain(null, perms); jaroslav@56: } jaroslav@56: pd = allPermDomain; jaroslav@56: } jaroslav@56: return pd; jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the ProtectionDomain of this class. jaroslav@56: */ jaroslav@56: private native java.security.ProtectionDomain getProtectionDomain0(); jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Set the ProtectionDomain for this class. Called by jaroslav@56: * ClassLoader.defineClass. jaroslav@56: */ jaroslav@56: native void setProtectionDomain0(java.security.ProtectionDomain pd); jaroslav@56: jaroslav@56: jaroslav@56: /* jaroslav@56: * Return the Virtual Machine's Class object for the named jaroslav@56: * primitive type. jaroslav@56: */ jaroslav@56: static native Class getPrimitiveClass(String name); jaroslav@56: jaroslav@56: jaroslav@56: /* jaroslav@56: * Check if client is allowed to access members. If access is denied, jaroslav@56: * throw a SecurityException. jaroslav@56: * jaroslav@56: * Be very careful not to change the stack depth of this checkMemberAccess jaroslav@56: * call for security reasons. jaroslav@56: * See java.lang.SecurityManager.checkMemberAccess. jaroslav@56: * jaroslav@56: *

Default policy: allow all clients access with normal Java access jaroslav@56: * control. jaroslav@56: */ jaroslav@56: private void checkMemberAccess(int which, ClassLoader ccl) { jaroslav@56: SecurityManager s = System.getSecurityManager(); jaroslav@56: if (s != null) { jaroslav@56: s.checkMemberAccess(this, which); jaroslav@56: ClassLoader cl = getClassLoader0(); jaroslav@56: if ((ccl != null) && (ccl != cl) && jaroslav@56: ((cl == null) || !cl.isAncestor(ccl))) { jaroslav@56: String name = this.getName(); jaroslav@56: int i = name.lastIndexOf('.'); jaroslav@56: if (i != -1) { jaroslav@56: s.checkPackageAccess(name.substring(0, i)); jaroslav@56: } jaroslav@56: } jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Add a package name prefix if the name is not absolute Remove leading "/" jaroslav@56: * if name is absolute jaroslav@56: */ jaroslav@56: private String resolveName(String name) { jaroslav@56: if (name == null) { jaroslav@56: return name; jaroslav@56: } jaroslav@56: if (!name.startsWith("/")) { jaroslav@56: Class c = this; jaroslav@56: while (c.isArray()) { jaroslav@56: c = c.getComponentType(); jaroslav@56: } jaroslav@56: String baseName = c.getName(); jaroslav@56: int index = baseName.lastIndexOf('.'); jaroslav@56: if (index != -1) { jaroslav@56: name = baseName.substring(0, index).replace('.', '/') jaroslav@56: +"/"+name; jaroslav@56: } jaroslav@56: } else { jaroslav@56: name = name.substring(1); jaroslav@56: } jaroslav@56: return name; jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Reflection support. jaroslav@56: */ jaroslav@56: jaroslav@56: // Caches for certain reflective results jaroslav@56: private static boolean useCaches = true; jaroslav@56: private volatile transient SoftReference declaredFields; jaroslav@56: private volatile transient SoftReference publicFields; jaroslav@56: private volatile transient SoftReference declaredMethods; jaroslav@56: private volatile transient SoftReference publicMethods; jaroslav@56: private volatile transient SoftReference[]> declaredConstructors; jaroslav@56: private volatile transient SoftReference[]> publicConstructors; jaroslav@56: // Intermediate results for getFields and getMethods jaroslav@56: private volatile transient SoftReference declaredPublicFields; jaroslav@56: private volatile transient SoftReference declaredPublicMethods; jaroslav@56: jaroslav@56: // Incremented by the VM on each call to JVM TI RedefineClasses() jaroslav@56: // that redefines this class or a superclass. jaroslav@56: private volatile transient int classRedefinedCount = 0; jaroslav@56: jaroslav@56: // Value of classRedefinedCount when we last cleared the cached values jaroslav@56: // that are sensitive to class redefinition. jaroslav@56: private volatile transient int lastRedefinedCount = 0; jaroslav@56: jaroslav@56: // Clears cached values that might possibly have been obsoleted by jaroslav@56: // a class redefinition. jaroslav@56: private void clearCachesOnClassRedefinition() { jaroslav@56: if (lastRedefinedCount != classRedefinedCount) { jaroslav@56: declaredFields = publicFields = declaredPublicFields = null; jaroslav@56: declaredMethods = publicMethods = declaredPublicMethods = null; jaroslav@56: declaredConstructors = publicConstructors = null; jaroslav@56: annotations = declaredAnnotations = null; jaroslav@56: jaroslav@56: // Use of "volatile" (and synchronization by caller in the case jaroslav@56: // of annotations) ensures that no thread sees the update to jaroslav@56: // lastRedefinedCount before seeing the caches cleared. jaroslav@56: // We do not guard against brief windows during which multiple jaroslav@56: // threads might redundantly work to fill an empty cache. jaroslav@56: lastRedefinedCount = classRedefinedCount; jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: // Generic signature handling jaroslav@56: private native String getGenericSignature(); jaroslav@56: jaroslav@56: // Generic info repository; lazily initialized jaroslav@56: private transient ClassRepository genericInfo; jaroslav@56: jaroslav@56: // accessor for factory jaroslav@56: private GenericsFactory getFactory() { jaroslav@56: // create scope and factory jaroslav@56: return CoreReflectionFactory.make(this, ClassScope.make(this)); jaroslav@56: } jaroslav@56: jaroslav@56: // accessor for generic info repository jaroslav@56: private ClassRepository getGenericInfo() { jaroslav@56: // lazily initialize repository if necessary jaroslav@56: if (genericInfo == null) { jaroslav@56: // create and cache generic info repository jaroslav@56: genericInfo = ClassRepository.make(getGenericSignature(), jaroslav@56: getFactory()); jaroslav@56: } jaroslav@56: return genericInfo; //return cached repository jaroslav@56: } jaroslav@56: jaroslav@56: // Annotations handling jaroslav@56: private native byte[] getRawAnnotations(); jaroslav@56: jaroslav@56: native ConstantPool getConstantPool(); jaroslav@56: jaroslav@56: // jaroslav@56: // jaroslav@56: // java.lang.reflect.Field handling jaroslav@56: // jaroslav@56: // jaroslav@56: jaroslav@56: // Returns an array of "root" fields. These Field objects must NOT jaroslav@56: // be propagated to the outside world, but must instead be copied jaroslav@56: // via ReflectionFactory.copyField. jaroslav@56: private Field[] privateGetDeclaredFields(boolean publicOnly) { jaroslav@56: checkInitted(); jaroslav@56: Field[] res = null; jaroslav@56: if (useCaches) { jaroslav@56: clearCachesOnClassRedefinition(); jaroslav@56: if (publicOnly) { jaroslav@56: if (declaredPublicFields != null) { jaroslav@56: res = declaredPublicFields.get(); jaroslav@56: } jaroslav@56: } else { jaroslav@56: if (declaredFields != null) { jaroslav@56: res = declaredFields.get(); jaroslav@56: } jaroslav@56: } jaroslav@56: if (res != null) return res; jaroslav@56: } jaroslav@56: // No cached value available; request value from VM jaroslav@56: res = Reflection.filterFields(this, getDeclaredFields0(publicOnly)); jaroslav@56: if (useCaches) { jaroslav@56: if (publicOnly) { jaroslav@56: declaredPublicFields = new SoftReference<>(res); jaroslav@56: } else { jaroslav@56: declaredFields = new SoftReference<>(res); jaroslav@56: } jaroslav@56: } jaroslav@56: return res; jaroslav@56: } jaroslav@56: jaroslav@56: // Returns an array of "root" fields. These Field objects must NOT jaroslav@56: // be propagated to the outside world, but must instead be copied jaroslav@56: // via ReflectionFactory.copyField. jaroslav@56: private Field[] privateGetPublicFields(Set> traversedInterfaces) { jaroslav@56: checkInitted(); jaroslav@56: Field[] res = null; jaroslav@56: if (useCaches) { jaroslav@56: clearCachesOnClassRedefinition(); jaroslav@56: if (publicFields != null) { jaroslav@56: res = publicFields.get(); jaroslav@56: } jaroslav@56: if (res != null) return res; jaroslav@56: } jaroslav@56: jaroslav@56: // No cached value available; compute value recursively. jaroslav@56: // Traverse in correct order for getField(). jaroslav@56: List fields = new ArrayList<>(); jaroslav@56: if (traversedInterfaces == null) { jaroslav@56: traversedInterfaces = new HashSet<>(); jaroslav@56: } jaroslav@56: jaroslav@56: // Local fields jaroslav@56: Field[] tmp = privateGetDeclaredFields(true); jaroslav@56: addAll(fields, tmp); jaroslav@56: jaroslav@56: // Direct superinterfaces, recursively jaroslav@56: for (Class c : getInterfaces()) { jaroslav@56: if (!traversedInterfaces.contains(c)) { jaroslav@56: traversedInterfaces.add(c); jaroslav@56: addAll(fields, c.privateGetPublicFields(traversedInterfaces)); jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: // Direct superclass, recursively jaroslav@56: if (!isInterface()) { jaroslav@56: Class c = getSuperclass(); jaroslav@56: if (c != null) { jaroslav@56: addAll(fields, c.privateGetPublicFields(traversedInterfaces)); jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: res = new Field[fields.size()]; jaroslav@56: fields.toArray(res); jaroslav@56: if (useCaches) { jaroslav@56: publicFields = new SoftReference<>(res); jaroslav@56: } jaroslav@56: return res; jaroslav@56: } jaroslav@56: jaroslav@56: private static void addAll(Collection c, Field[] o) { jaroslav@56: for (int i = 0; i < o.length; i++) { jaroslav@56: c.add(o[i]); jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: // jaroslav@56: // jaroslav@56: // java.lang.reflect.Constructor handling jaroslav@56: // jaroslav@56: // jaroslav@56: jaroslav@56: // Returns an array of "root" constructors. These Constructor jaroslav@56: // objects must NOT be propagated to the outside world, but must jaroslav@56: // instead be copied via ReflectionFactory.copyConstructor. jaroslav@56: private Constructor[] privateGetDeclaredConstructors(boolean publicOnly) { jaroslav@56: checkInitted(); jaroslav@56: Constructor[] res = null; jaroslav@56: if (useCaches) { jaroslav@56: clearCachesOnClassRedefinition(); jaroslav@56: if (publicOnly) { jaroslav@56: if (publicConstructors != null) { jaroslav@56: res = publicConstructors.get(); jaroslav@56: } jaroslav@56: } else { jaroslav@56: if (declaredConstructors != null) { jaroslav@56: res = declaredConstructors.get(); jaroslav@56: } jaroslav@56: } jaroslav@56: if (res != null) return res; jaroslav@56: } jaroslav@56: // No cached value available; request value from VM jaroslav@56: if (isInterface()) { jaroslav@56: res = new Constructor[0]; jaroslav@56: } else { jaroslav@56: res = getDeclaredConstructors0(publicOnly); jaroslav@56: } jaroslav@56: if (useCaches) { jaroslav@56: if (publicOnly) { jaroslav@56: publicConstructors = new SoftReference<>(res); jaroslav@56: } else { jaroslav@56: declaredConstructors = new SoftReference<>(res); jaroslav@56: } jaroslav@56: } jaroslav@56: return res; jaroslav@56: } jaroslav@56: jaroslav@56: // jaroslav@56: // jaroslav@56: // java.lang.reflect.Method handling jaroslav@56: // jaroslav@56: // jaroslav@56: jaroslav@56: // Returns an array of "root" methods. These Method objects must NOT jaroslav@56: // be propagated to the outside world, but must instead be copied jaroslav@56: // via ReflectionFactory.copyMethod. jaroslav@56: private Method[] privateGetDeclaredMethods(boolean publicOnly) { jaroslav@56: checkInitted(); jaroslav@56: Method[] res = null; jaroslav@56: if (useCaches) { jaroslav@56: clearCachesOnClassRedefinition(); jaroslav@56: if (publicOnly) { jaroslav@56: if (declaredPublicMethods != null) { jaroslav@56: res = declaredPublicMethods.get(); jaroslav@56: } jaroslav@56: } else { jaroslav@56: if (declaredMethods != null) { jaroslav@56: res = declaredMethods.get(); jaroslav@56: } jaroslav@56: } jaroslav@56: if (res != null) return res; jaroslav@56: } jaroslav@56: // No cached value available; request value from VM jaroslav@56: res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly)); jaroslav@56: if (useCaches) { jaroslav@56: if (publicOnly) { jaroslav@56: declaredPublicMethods = new SoftReference<>(res); jaroslav@56: } else { jaroslav@56: declaredMethods = new SoftReference<>(res); jaroslav@56: } jaroslav@56: } jaroslav@56: return res; jaroslav@56: } jaroslav@56: jaroslav@56: static class MethodArray { jaroslav@56: private Method[] methods; jaroslav@56: private int length; jaroslav@56: jaroslav@56: MethodArray() { jaroslav@56: methods = new Method[20]; jaroslav@56: length = 0; jaroslav@56: } jaroslav@56: jaroslav@56: void add(Method m) { jaroslav@56: if (length == methods.length) { jaroslav@56: methods = Arrays.copyOf(methods, 2 * methods.length); jaroslav@56: } jaroslav@56: methods[length++] = m; jaroslav@56: } jaroslav@56: jaroslav@56: void addAll(Method[] ma) { jaroslav@56: for (int i = 0; i < ma.length; i++) { jaroslav@56: add(ma[i]); jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: void addAll(MethodArray ma) { jaroslav@56: for (int i = 0; i < ma.length(); i++) { jaroslav@56: add(ma.get(i)); jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: void addIfNotPresent(Method newMethod) { jaroslav@56: for (int i = 0; i < length; i++) { jaroslav@56: Method m = methods[i]; jaroslav@56: if (m == newMethod || (m != null && m.equals(newMethod))) { jaroslav@56: return; jaroslav@56: } jaroslav@56: } jaroslav@56: add(newMethod); jaroslav@56: } jaroslav@56: jaroslav@56: void addAllIfNotPresent(MethodArray newMethods) { jaroslav@56: for (int i = 0; i < newMethods.length(); i++) { jaroslav@56: Method m = newMethods.get(i); jaroslav@56: if (m != null) { jaroslav@56: addIfNotPresent(m); jaroslav@56: } jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: int length() { jaroslav@56: return length; jaroslav@56: } jaroslav@56: jaroslav@56: Method get(int i) { jaroslav@56: return methods[i]; jaroslav@56: } jaroslav@56: jaroslav@56: void removeByNameAndSignature(Method toRemove) { jaroslav@56: for (int i = 0; i < length; i++) { jaroslav@56: Method m = methods[i]; jaroslav@56: if (m != null && jaroslav@56: m.getReturnType() == toRemove.getReturnType() && jaroslav@56: m.getName() == toRemove.getName() && jaroslav@56: arrayContentsEq(m.getParameterTypes(), jaroslav@56: toRemove.getParameterTypes())) { jaroslav@56: methods[i] = null; jaroslav@56: } jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: void compactAndTrim() { jaroslav@56: int newPos = 0; jaroslav@56: // Get rid of null slots jaroslav@56: for (int pos = 0; pos < length; pos++) { jaroslav@56: Method m = methods[pos]; jaroslav@56: if (m != null) { jaroslav@56: if (pos != newPos) { jaroslav@56: methods[newPos] = m; jaroslav@56: } jaroslav@56: newPos++; jaroslav@56: } jaroslav@56: } jaroslav@56: if (newPos != methods.length) { jaroslav@56: methods = Arrays.copyOf(methods, newPos); jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: Method[] getArray() { jaroslav@56: return methods; jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: // Returns an array of "root" methods. These Method objects must NOT jaroslav@56: // be propagated to the outside world, but must instead be copied jaroslav@56: // via ReflectionFactory.copyMethod. jaroslav@56: private Method[] privateGetPublicMethods() { jaroslav@56: checkInitted(); jaroslav@56: Method[] res = null; jaroslav@56: if (useCaches) { jaroslav@56: clearCachesOnClassRedefinition(); jaroslav@56: if (publicMethods != null) { jaroslav@56: res = publicMethods.get(); jaroslav@56: } jaroslav@56: if (res != null) return res; jaroslav@56: } jaroslav@56: jaroslav@56: // No cached value available; compute value recursively. jaroslav@56: // Start by fetching public declared methods jaroslav@56: MethodArray methods = new MethodArray(); jaroslav@56: { jaroslav@56: Method[] tmp = privateGetDeclaredMethods(true); jaroslav@56: methods.addAll(tmp); jaroslav@56: } jaroslav@56: // Now recur over superclass and direct superinterfaces. jaroslav@56: // Go over superinterfaces first so we can more easily filter jaroslav@56: // out concrete implementations inherited from superclasses at jaroslav@56: // the end. jaroslav@56: MethodArray inheritedMethods = new MethodArray(); jaroslav@56: Class[] interfaces = getInterfaces(); jaroslav@56: for (int i = 0; i < interfaces.length; i++) { jaroslav@56: inheritedMethods.addAll(interfaces[i].privateGetPublicMethods()); jaroslav@56: } jaroslav@56: if (!isInterface()) { jaroslav@56: Class c = getSuperclass(); jaroslav@56: if (c != null) { jaroslav@56: MethodArray supers = new MethodArray(); jaroslav@56: supers.addAll(c.privateGetPublicMethods()); jaroslav@56: // Filter out concrete implementations of any jaroslav@56: // interface methods jaroslav@56: for (int i = 0; i < supers.length(); i++) { jaroslav@56: Method m = supers.get(i); jaroslav@56: if (m != null && !Modifier.isAbstract(m.getModifiers())) { jaroslav@56: inheritedMethods.removeByNameAndSignature(m); jaroslav@56: } jaroslav@56: } jaroslav@56: // Insert superclass's inherited methods before jaroslav@56: // superinterfaces' to satisfy getMethod's search jaroslav@56: // order jaroslav@56: supers.addAll(inheritedMethods); jaroslav@56: inheritedMethods = supers; jaroslav@56: } jaroslav@56: } jaroslav@56: // Filter out all local methods from inherited ones jaroslav@56: for (int i = 0; i < methods.length(); i++) { jaroslav@56: Method m = methods.get(i); jaroslav@56: inheritedMethods.removeByNameAndSignature(m); jaroslav@56: } jaroslav@56: methods.addAllIfNotPresent(inheritedMethods); jaroslav@56: methods.compactAndTrim(); jaroslav@56: res = methods.getArray(); jaroslav@56: if (useCaches) { jaroslav@56: publicMethods = new SoftReference<>(res); jaroslav@56: } jaroslav@56: return res; jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: // jaroslav@56: // Helpers for fetchers of one field, method, or constructor jaroslav@56: // jaroslav@56: jaroslav@56: private Field searchFields(Field[] fields, String name) { jaroslav@56: String internedName = name.intern(); jaroslav@56: for (int i = 0; i < fields.length; i++) { jaroslav@56: if (fields[i].getName() == internedName) { jaroslav@56: return getReflectionFactory().copyField(fields[i]); jaroslav@56: } jaroslav@56: } jaroslav@56: return null; jaroslav@56: } jaroslav@56: jaroslav@56: private Field getField0(String name) throws NoSuchFieldException { jaroslav@56: // Note: the intent is that the search algorithm this routine jaroslav@56: // uses be equivalent to the ordering imposed by jaroslav@56: // privateGetPublicFields(). It fetches only the declared jaroslav@56: // public fields for each class, however, to reduce the number jaroslav@56: // of Field objects which have to be created for the common jaroslav@56: // case where the field being requested is declared in the jaroslav@56: // class which is being queried. jaroslav@56: Field res = null; jaroslav@56: // Search declared public fields jaroslav@56: if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { jaroslav@56: return res; jaroslav@56: } jaroslav@56: // Direct superinterfaces, recursively jaroslav@56: Class[] interfaces = getInterfaces(); jaroslav@56: for (int i = 0; i < interfaces.length; i++) { jaroslav@56: Class c = interfaces[i]; jaroslav@56: if ((res = c.getField0(name)) != null) { jaroslav@56: return res; jaroslav@56: } jaroslav@56: } jaroslav@56: // Direct superclass, recursively jaroslav@56: if (!isInterface()) { jaroslav@56: Class c = getSuperclass(); jaroslav@56: if (c != null) { jaroslav@56: if ((res = c.getField0(name)) != null) { jaroslav@56: return res; jaroslav@56: } jaroslav@56: } jaroslav@56: } jaroslav@56: return null; jaroslav@56: } jaroslav@56: jaroslav@56: private static Method searchMethods(Method[] methods, jaroslav@56: String name, jaroslav@56: Class[] parameterTypes) jaroslav@56: { jaroslav@56: Method res = null; jaroslav@56: String internedName = name.intern(); jaroslav@56: for (int i = 0; i < methods.length; i++) { jaroslav@56: Method m = methods[i]; jaroslav@56: if (m.getName() == internedName jaroslav@56: && arrayContentsEq(parameterTypes, m.getParameterTypes()) jaroslav@56: && (res == null jaroslav@56: || res.getReturnType().isAssignableFrom(m.getReturnType()))) jaroslav@56: res = m; jaroslav@56: } jaroslav@56: jaroslav@56: return (res == null ? res : getReflectionFactory().copyMethod(res)); jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: private Method getMethod0(String name, Class[] parameterTypes) { jaroslav@56: // Note: the intent is that the search algorithm this routine jaroslav@56: // uses be equivalent to the ordering imposed by jaroslav@56: // privateGetPublicMethods(). It fetches only the declared jaroslav@56: // public methods for each class, however, to reduce the jaroslav@56: // number of Method objects which have to be created for the jaroslav@56: // common case where the method being requested is declared in jaroslav@56: // the class which is being queried. jaroslav@56: Method res = null; jaroslav@56: // Search declared public methods jaroslav@56: if ((res = searchMethods(privateGetDeclaredMethods(true), jaroslav@56: name, jaroslav@56: parameterTypes)) != null) { jaroslav@56: return res; jaroslav@56: } jaroslav@56: // Search superclass's methods jaroslav@56: if (!isInterface()) { jaroslav@56: Class c = getSuperclass(); jaroslav@56: if (c != null) { jaroslav@56: if ((res = c.getMethod0(name, parameterTypes)) != null) { jaroslav@56: return res; jaroslav@56: } jaroslav@56: } jaroslav@56: } jaroslav@56: // Search superinterfaces' methods jaroslav@56: Class[] interfaces = getInterfaces(); jaroslav@56: for (int i = 0; i < interfaces.length; i++) { jaroslav@56: Class c = interfaces[i]; jaroslav@56: if ((res = c.getMethod0(name, parameterTypes)) != null) { jaroslav@56: return res; jaroslav@56: } jaroslav@56: } jaroslav@56: // Not found jaroslav@56: return null; jaroslav@56: } jaroslav@56: jaroslav@56: private Constructor getConstructor0(Class[] parameterTypes, jaroslav@56: int which) throws NoSuchMethodException jaroslav@56: { jaroslav@56: Constructor[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC)); jaroslav@56: for (Constructor constructor : constructors) { jaroslav@56: if (arrayContentsEq(parameterTypes, jaroslav@56: constructor.getParameterTypes())) { jaroslav@56: return getReflectionFactory().copyConstructor(constructor); jaroslav@56: } jaroslav@56: } jaroslav@56: throw new NoSuchMethodException(getName() + "." + argumentTypesToString(parameterTypes)); jaroslav@56: } jaroslav@56: jaroslav@56: // jaroslav@56: // Other helpers and base implementation jaroslav@56: // jaroslav@56: jaroslav@56: private static boolean arrayContentsEq(Object[] a1, Object[] a2) { jaroslav@56: if (a1 == null) { jaroslav@56: return a2 == null || a2.length == 0; jaroslav@56: } jaroslav@56: jaroslav@56: if (a2 == null) { jaroslav@56: return a1.length == 0; jaroslav@56: } jaroslav@56: jaroslav@56: if (a1.length != a2.length) { jaroslav@56: return false; jaroslav@56: } jaroslav@56: jaroslav@56: for (int i = 0; i < a1.length; i++) { jaroslav@56: if (a1[i] != a2[i]) { jaroslav@56: return false; jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: return true; jaroslav@56: } jaroslav@56: jaroslav@56: private static Field[] copyFields(Field[] arg) { jaroslav@56: Field[] out = new Field[arg.length]; jaroslav@56: ReflectionFactory fact = getReflectionFactory(); jaroslav@56: for (int i = 0; i < arg.length; i++) { jaroslav@56: out[i] = fact.copyField(arg[i]); jaroslav@56: } jaroslav@56: return out; jaroslav@56: } jaroslav@56: jaroslav@56: private static Method[] copyMethods(Method[] arg) { jaroslav@56: Method[] out = new Method[arg.length]; jaroslav@56: ReflectionFactory fact = getReflectionFactory(); jaroslav@56: for (int i = 0; i < arg.length; i++) { jaroslav@56: out[i] = fact.copyMethod(arg[i]); jaroslav@56: } jaroslav@56: return out; jaroslav@56: } jaroslav@56: jaroslav@56: private static Constructor[] copyConstructors(Constructor[] arg) { jaroslav@56: Constructor[] out = arg.clone(); jaroslav@56: ReflectionFactory fact = getReflectionFactory(); jaroslav@56: for (int i = 0; i < out.length; i++) { jaroslav@56: out[i] = fact.copyConstructor(out[i]); jaroslav@56: } jaroslav@56: return out; jaroslav@56: } jaroslav@56: jaroslav@56: private native Field[] getDeclaredFields0(boolean publicOnly); jaroslav@56: private native Method[] getDeclaredMethods0(boolean publicOnly); jaroslav@56: private native Constructor[] getDeclaredConstructors0(boolean publicOnly); jaroslav@56: private native Class[] getDeclaredClasses0(); jaroslav@56: jaroslav@56: private static String argumentTypesToString(Class[] argTypes) { jaroslav@56: StringBuilder buf = new StringBuilder(); jaroslav@56: buf.append("("); jaroslav@56: if (argTypes != null) { jaroslav@56: for (int i = 0; i < argTypes.length; i++) { jaroslav@56: if (i > 0) { jaroslav@56: buf.append(", "); jaroslav@56: } jaroslav@56: Class c = argTypes[i]; jaroslav@56: buf.append((c == null) ? "null" : c.getName()); jaroslav@56: } jaroslav@56: } jaroslav@56: buf.append(")"); jaroslav@56: return buf.toString(); jaroslav@56: } jaroslav@56: jaroslav@56: /** use serialVersionUID from JDK 1.1 for interoperability */ jaroslav@56: private static final long serialVersionUID = 3206093459760846163L; jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Class Class is special cased within the Serialization Stream Protocol. jaroslav@56: * jaroslav@56: * A Class instance is written initially into an ObjectOutputStream in the jaroslav@56: * following format: jaroslav@56: *

jaroslav@56:      *      {@code TC_CLASS} ClassDescriptor
jaroslav@56:      *      A ClassDescriptor is a special cased serialization of
jaroslav@56:      *      a {@code java.io.ObjectStreamClass} instance.
jaroslav@56:      * 
jaroslav@56: * A new handle is generated for the initial time the class descriptor jaroslav@56: * is written into the stream. Future references to the class descriptor jaroslav@56: * are written as references to the initial class descriptor instance. jaroslav@56: * jaroslav@56: * @see java.io.ObjectStreamClass jaroslav@56: */ jaroslav@56: private static final ObjectStreamField[] serialPersistentFields = jaroslav@56: new ObjectStreamField[0]; jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the assertion status that would be assigned to this jaroslav@56: * class if it were to be initialized at the time this method is invoked. jaroslav@56: * If this class has had its assertion status set, the most recent jaroslav@56: * setting will be returned; otherwise, if any package default assertion jaroslav@56: * status pertains to this class, the most recent setting for the most jaroslav@56: * specific pertinent package default assertion status is returned; jaroslav@56: * otherwise, if this class is not a system class (i.e., it has a jaroslav@56: * class loader) its class loader's default assertion status is returned; jaroslav@56: * otherwise, the system class default assertion status is returned. jaroslav@56: *

jaroslav@56: * Few programmers will have any need for this method; it is provided jaroslav@56: * for the benefit of the JRE itself. (It allows a class to determine at jaroslav@56: * the time that it is initialized whether assertions should be enabled.) jaroslav@56: * Note that this method is not guaranteed to return the actual jaroslav@56: * assertion status that was (or will be) associated with the specified jaroslav@56: * class when it was (or will be) initialized. jaroslav@56: * jaroslav@56: * @return the desired assertion status of the specified class. jaroslav@56: * @see java.lang.ClassLoader#setClassAssertionStatus jaroslav@56: * @see java.lang.ClassLoader#setPackageAssertionStatus jaroslav@56: * @see java.lang.ClassLoader#setDefaultAssertionStatus jaroslav@56: * @since 1.4 jaroslav@56: */ jaroslav@56: public boolean desiredAssertionStatus() { jaroslav@56: ClassLoader loader = getClassLoader(); jaroslav@56: // If the loader is null this is a system class, so ask the VM jaroslav@56: if (loader == null) jaroslav@56: return desiredAssertionStatus0(this); jaroslav@56: jaroslav@56: // If the classloader has been initialized with the assertion jaroslav@56: // directives, ask it. Otherwise, ask the VM. jaroslav@56: synchronized(loader.assertionLock) { jaroslav@56: if (loader.classAssertionStatus != null) { jaroslav@56: return loader.desiredAssertionStatus(getName()); jaroslav@56: } jaroslav@56: } jaroslav@56: return desiredAssertionStatus0(this); jaroslav@56: } jaroslav@56: jaroslav@56: // Retrieves the desired assertion status of this class from the VM jaroslav@56: private static native boolean desiredAssertionStatus0(Class clazz); jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns true if and only if this class was declared as an enum in the jaroslav@56: * source code. jaroslav@56: * jaroslav@56: * @return true if and only if this class was declared as an enum in the jaroslav@56: * source code jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public boolean isEnum() { jaroslav@56: // An enum must both directly extend java.lang.Enum and have jaroslav@56: // the ENUM bit set; classes for specialized enum constants jaroslav@56: // don't do the former. jaroslav@56: return (this.getModifiers() & ENUM) != 0 && jaroslav@56: this.getSuperclass() == java.lang.Enum.class; jaroslav@56: } jaroslav@56: jaroslav@56: // Fetches the factory for reflective objects jaroslav@56: private static ReflectionFactory getReflectionFactory() { jaroslav@56: if (reflectionFactory == null) { jaroslav@56: reflectionFactory = jaroslav@56: java.security.AccessController.doPrivileged jaroslav@56: (new sun.reflect.ReflectionFactory.GetReflectionFactoryAction()); jaroslav@56: } jaroslav@56: return reflectionFactory; jaroslav@56: } jaroslav@56: private static ReflectionFactory reflectionFactory; jaroslav@56: jaroslav@56: // To be able to query system properties as soon as they're available jaroslav@56: private static boolean initted = false; jaroslav@56: private static void checkInitted() { jaroslav@56: if (initted) return; jaroslav@56: AccessController.doPrivileged(new PrivilegedAction() { jaroslav@56: public Void run() { jaroslav@56: // Tests to ensure the system properties table is fully jaroslav@56: // initialized. This is needed because reflection code is jaroslav@56: // called very early in the initialization process (before jaroslav@56: // command-line arguments have been parsed and therefore jaroslav@56: // these user-settable properties installed.) We assume that jaroslav@56: // if System.out is non-null then the System class has been jaroslav@56: // fully initialized and that the bulk of the startup code jaroslav@56: // has been run. jaroslav@56: jaroslav@56: if (System.out == null) { jaroslav@56: // java.lang.System not yet fully initialized jaroslav@56: return null; jaroslav@56: } jaroslav@56: jaroslav@56: String val = jaroslav@56: System.getProperty("sun.reflect.noCaches"); jaroslav@56: if (val != null && val.equals("true")) { jaroslav@56: useCaches = false; jaroslav@56: } jaroslav@56: jaroslav@56: initted = true; jaroslav@56: return null; jaroslav@56: } jaroslav@56: }); jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the elements of this enum class or null if this jaroslav@56: * Class object does not represent an enum type. jaroslav@56: * jaroslav@56: * @return an array containing the values comprising the enum class jaroslav@56: * represented by this Class object in the order they're jaroslav@56: * declared, or null if this Class object does not jaroslav@56: * represent an enum type jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public T[] getEnumConstants() { jaroslav@56: T[] values = getEnumConstantsShared(); jaroslav@56: return (values != null) ? values.clone() : null; jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns the elements of this enum class or null if this jaroslav@56: * Class object does not represent an enum type; jaroslav@56: * identical to getEnumConstants except that the result is jaroslav@56: * uncloned, cached, and shared by all callers. jaroslav@56: */ jaroslav@56: T[] getEnumConstantsShared() { jaroslav@56: if (enumConstants == null) { jaroslav@56: if (!isEnum()) return null; jaroslav@56: try { jaroslav@56: final Method values = getMethod("values"); jaroslav@56: java.security.AccessController.doPrivileged( jaroslav@56: new java.security.PrivilegedAction() { jaroslav@56: public Void run() { jaroslav@56: values.setAccessible(true); jaroslav@56: return null; jaroslav@56: } jaroslav@56: }); jaroslav@56: enumConstants = (T[])values.invoke(null); jaroslav@56: } jaroslav@56: // These can happen when users concoct enum-like classes jaroslav@56: // that don't comply with the enum spec. jaroslav@56: catch (InvocationTargetException ex) { return null; } jaroslav@56: catch (NoSuchMethodException ex) { return null; } jaroslav@56: catch (IllegalAccessException ex) { return null; } jaroslav@56: } jaroslav@56: return enumConstants; jaroslav@56: } jaroslav@56: private volatile transient T[] enumConstants = null; jaroslav@56: jaroslav@56: /** jaroslav@56: * Returns a map from simple name to enum constant. This package-private jaroslav@56: * method is used internally by Enum to implement jaroslav@56: * public static > T valueOf(Class, String) jaroslav@56: * efficiently. Note that the map is returned by this method is jaroslav@56: * created lazily on first use. Typically it won't ever get created. jaroslav@56: */ jaroslav@56: Map enumConstantDirectory() { jaroslav@56: if (enumConstantDirectory == null) { jaroslav@56: T[] universe = getEnumConstantsShared(); jaroslav@56: if (universe == null) jaroslav@56: throw new IllegalArgumentException( jaroslav@56: getName() + " is not an enum type"); jaroslav@56: Map m = new HashMap<>(2 * universe.length); jaroslav@56: for (T constant : universe) jaroslav@56: m.put(((Enum)constant).name(), constant); jaroslav@56: enumConstantDirectory = m; jaroslav@56: } jaroslav@56: return enumConstantDirectory; jaroslav@56: } jaroslav@56: private volatile transient Map enumConstantDirectory = null; jaroslav@56: jaroslav@56: /** jaroslav@56: * Casts an object to the class or interface represented jaroslav@56: * by this {@code Class} object. jaroslav@56: * jaroslav@56: * @param obj the object to be cast jaroslav@56: * @return the object after casting, or null if obj is null jaroslav@56: * jaroslav@56: * @throws ClassCastException if the object is not jaroslav@56: * null and is not assignable to the type T. jaroslav@56: * jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public T cast(Object obj) { jaroslav@56: if (obj != null && !isInstance(obj)) jaroslav@56: throw new ClassCastException(cannotCastMsg(obj)); jaroslav@56: return (T) obj; jaroslav@56: } jaroslav@56: jaroslav@56: private String cannotCastMsg(Object obj) { jaroslav@56: return "Cannot cast " + obj.getClass().getName() + " to " + getName(); jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * Casts this {@code Class} object to represent a subclass of the class jaroslav@56: * represented by the specified class object. Checks that that the cast jaroslav@56: * is valid, and throws a {@code ClassCastException} if it is not. If jaroslav@56: * this method succeeds, it always returns a reference to this class object. jaroslav@56: * jaroslav@56: *

This method is useful when a client needs to "narrow" the type of jaroslav@56: * a {@code Class} object to pass it to an API that restricts the jaroslav@56: * {@code Class} objects that it is willing to accept. A cast would jaroslav@56: * generate a compile-time warning, as the correctness of the cast jaroslav@56: * could not be checked at runtime (because generic types are implemented jaroslav@56: * by erasure). jaroslav@56: * jaroslav@56: * @return this {@code Class} object, cast to represent a subclass of jaroslav@56: * the specified class object. jaroslav@56: * @throws ClassCastException if this {@code Class} object does not jaroslav@56: * represent a subclass of the specified class (here "subclass" includes jaroslav@56: * the class itself). jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public Class asSubclass(Class clazz) { jaroslav@56: if (clazz.isAssignableFrom(this)) jaroslav@56: return (Class) this; jaroslav@56: else jaroslav@56: throw new ClassCastException(this.toString()); jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * @throws NullPointerException {@inheritDoc} jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public A getAnnotation(Class annotationClass) { jaroslav@56: if (annotationClass == null) jaroslav@56: throw new NullPointerException(); jaroslav@56: jaroslav@56: initAnnotationsIfNecessary(); jaroslav@56: return (A) annotations.get(annotationClass); jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * @throws NullPointerException {@inheritDoc} jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public boolean isAnnotationPresent( jaroslav@56: Class annotationClass) { jaroslav@56: if (annotationClass == null) jaroslav@56: throw new NullPointerException(); jaroslav@56: jaroslav@56: return getAnnotation(annotationClass) != null; jaroslav@56: } jaroslav@56: jaroslav@56: jaroslav@56: /** jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public Annotation[] getAnnotations() { jaroslav@56: initAnnotationsIfNecessary(); jaroslav@56: return AnnotationParser.toArray(annotations); jaroslav@56: } jaroslav@56: jaroslav@56: /** jaroslav@56: * @since 1.5 jaroslav@56: */ jaroslav@56: public Annotation[] getDeclaredAnnotations() { jaroslav@56: initAnnotationsIfNecessary(); jaroslav@56: return AnnotationParser.toArray(declaredAnnotations); jaroslav@56: } jaroslav@56: jaroslav@56: // Annotations cache jaroslav@56: private transient Map, Annotation> annotations; jaroslav@56: private transient Map, Annotation> declaredAnnotations; jaroslav@56: jaroslav@56: private synchronized void initAnnotationsIfNecessary() { jaroslav@56: clearCachesOnClassRedefinition(); jaroslav@56: if (annotations != null) jaroslav@56: return; jaroslav@56: declaredAnnotations = AnnotationParser.parseAnnotations( jaroslav@56: getRawAnnotations(), getConstantPool(), this); jaroslav@56: Class superClass = getSuperclass(); jaroslav@56: if (superClass == null) { jaroslav@56: annotations = declaredAnnotations; jaroslav@56: } else { jaroslav@56: annotations = new HashMap<>(); jaroslav@56: superClass.initAnnotationsIfNecessary(); jaroslav@56: for (Map.Entry, Annotation> e : superClass.annotations.entrySet()) { jaroslav@56: Class annotationClass = e.getKey(); jaroslav@56: if (AnnotationType.getInstance(annotationClass).isInherited()) jaroslav@56: annotations.put(annotationClass, e.getValue()); jaroslav@56: } jaroslav@56: annotations.putAll(declaredAnnotations); jaroslav@56: } jaroslav@56: } jaroslav@56: jaroslav@56: // Annotation types cache their internal (AnnotationType) form jaroslav@56: jaroslav@56: private AnnotationType annotationType; jaroslav@56: jaroslav@56: void setAnnotationType(AnnotationType type) { jaroslav@56: annotationType = type; jaroslav@56: } jaroslav@56: jaroslav@56: AnnotationType getAnnotationType() { jaroslav@56: return annotationType; jaroslav@56: } jaroslav@56: }