0
点赞
收藏
分享

微信扫一扫

Class源码

桑二小姐 2023-06-03 阅读 105
java

介绍

如果想要在程序运行阶段访问某个类的所有信息,并支持修改类的状态或者行为的话,肯定会用到反射,而反射靠的就是Class类。

通过Class类可以获取类的实例,构造方法,字段,成员方法,接口等信息。获取之后可以通过API进行相应的操作。

public final class Class<T> implements java.io.Serializable,
                              GenericDeclaration,
                              Type,
                              AnnotatedElement

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NGXRMgsz-1685746810777)(null)]

常量&变量

    //标识注解类型
    private static final int ANNOTATION= 0x00002000;
    //标识枚举类型
    private static final int ENUM      = 0x00004000;
    //表示该class文件并非由Java源代码所生成
    private static final int SYNTHETIC = 0x00001000;
    //注册本地方法
    private static native void registerNatives();
    static {
        registerNatives();
    }

    //缓存构造器
    private volatile transient Constructor<T> cachedConstructor;
    //调用者的缓存构造器
    private volatile transient Class<?>       newInstanceCallerCache;
    
    // cache the name to reduce the number of calls into the VM
    //实体的名称
    private transient String name;
    private native String getName0();
    
    // Package-private to allow ClassLoader access
    ClassLoader getClassLoader0() { return classLoader; }

    // Initialized in JVM not by private constructor
    // This field is filtered from reflection access, i.e. getDeclaredField
    // will throw NoSuchFieldException
    //类加载器
    private final ClassLoader classLoader;
    
    /** protection domain returned when the internal domain is null */
    //null值的安全返回
    private static java.security.ProtectionDomain allPermDomain;
    
    /**
     * Reflection support.
     */

    // Caches for certain reflective results
    //缓存反射结果
    private static boolean useCaches = true;
    
    //反射信息
    private volatile transient SoftReference<ReflectionData<T>> reflectionData;

    // Incremented by the VM on each call to JVM TI RedefineClasses()
    // that redefines this class or a superclass.
    //每次调用JVM时由VM递增
    private volatile transient int classRedefinedCount = 0;
    

    // Generic signature handling
    private native String getGenericSignature0();

    // Generic info repository; lazily initialized
    //通用信息
    private volatile transient ClassRepository genericInfo;
    
    
    /** use serialVersionUID from JDK 1.1 for interoperability */
    //序列化版本号
    private static final long serialVersionUID = 3206093459760846163L;


    /**
     * Class Class is special cased within the Serialization Stream Protocol.
     *
     * A Class instance is written initially into an ObjectOutputStream in the
     * following format:
     * <pre>
     *      {@code TC_CLASS} ClassDescriptor
     *      A ClassDescriptor is a special cased serialization of
     *      a {@code java.io.ObjectStreamClass} instance.
     * </pre>
     * A new handle is generated for the initial time the class descriptor
     * is written into the stream. Future references to the class descriptor
     * are written as references to the initial class descriptor instance.
     *
     * @see java.io.ObjectStreamClass
     */
    private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];
        

    //反射工厂
    private static ReflectionFactory reflectionFactory;

    // To be able to query system properties as soon as they're available
    //是否初始化
    private static boolean initted = false;
    private static void checkInitted() {
        if (initted) return;
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    // Tests to ensure the system properties table is fully
                    // initialized. This is needed because reflection code is
                    // called very early in the initialization process (before
                    // command-line arguments have been parsed and therefore
                    // these user-settable properties installed.) We assume that
                    // if System.out is non-null then the System class has been
                    // fully initialized and that the bulk of the startup code
                    // has been run.

                    if (System.out == null) {
                        // java.lang.System not yet fully initialized
                        return null;
                    }

                    // Doesn't use Boolean.getBoolean to avoid class init.
                    String val =
                        System.getProperty("sun.reflect.noCaches");
                    if (val != null && val.equals("true")) {
                        useCaches = false;
                    }

                    initted = true;
                    return null;
                }
            });
    }

    //枚举类常量 null
    private volatile transient T[] enumConstants = null;
    
    //枚举类常量目录
    private volatile transient Map<String, T> enumConstantDirectory = null;
    
    // Annotations cache
    @SuppressWarnings("UnusedDeclaration")
    //注解数据
    private volatile transient AnnotationData annotationData;
    
    @SuppressWarnings("UnusedDeclaration")
    //注解类型
    private volatile transient AnnotationType annotationType;
    
    /* Backing store of user-defined values pertaining to this class.
     * Maintained by the ClassValue class.
     */
    transient ClassValue.ClassValueMap classValueMap;

构造方法

    /*
     * Private constructor. Only the Java Virtual Machine creates Class objects.
     * This constructor is not used and prevents the default constructor being
     * generated.
     *只能由java虚拟机创建对象
     */
    private Class(ClassLoader loader) {
        // Initialize final field for classLoader.  The initialization value of non-null
        // prevents future JIT optimizations from assuming this final field is null.
        classLoader = loader;
    }

Class并不能直接通过new Class()获取实例。那么应该如何获取呢?

//直接通过类的静态变量来获取
Class<Integer> intClass = Integer.class;

//通过实例变量的getClass方法
Integer integer = new Integer(0);
Class<? extends Integer> aClass = integer.getClass();

//通过Class.forName("类的全限定名")
Class<?> aClass1 = Class.forName("java.lang.Integer");

常用方法

forName

    /**
     * Returns the {@code Class} object associated with the class or
     * interface with the given string name.  Invoking this method is
     * equivalent to:
     *
     * <blockquote>
     *  {@code Class.forName(className, true, currentLoader)}
     * </blockquote>
     *
     * where {@code currentLoader} denotes the defining class loader of
     * the current class.
     *
     * <p> For example, the following code fragment returns the
     * runtime {@code Class} descriptor for the class named
     * {@code java.lang.Thread}:
     *
     * <blockquote>
     *   {@code Class t = Class.forName("java.lang.Thread")}
     * </blockquote>
     * <p>
     * A call to {@code forName("X")} causes the class named
     * {@code X} to be initialized.
     *
     * @param      className   the fully qualified name of the desired class.
     * @return     the {@code Class} object for the class with the
     *             specified name.
     * @exception LinkageError if the linkage fails
     * @exception ExceptionInInitializerError if the initialization provoked
     *            by this method fails
     * @exception ClassNotFoundException if the class cannot be located
     * 手动加载一个类,
     */
    @CallerSensitive
    public static Class<?> forName(String className)
                throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }


    /**
     * Returns the {@code Class} object associated with the class or
     * interface with the given string name, using the given class loader.
     * Given the fully qualified name for a class or interface (in the same
     * format returned by {@code getName}) this method attempts to
     * locate, load, and link the class or interface.  The specified class
     * loader is used to load the class or interface.  If the parameter
     * {@code loader} is null, the class is loaded through the bootstrap
     * class loader.  The class is initialized only if the
     * {@code initialize} parameter is {@code true} and if it has
     * not been initialized earlier.
     *
     * <p> If {@code name} denotes a primitive type or void, an attempt
     * will be made to locate a user-defined class in the unnamed package whose
     * name is {@code name}. Therefore, this method cannot be used to
     * obtain any of the {@code Class} objects representing primitive
     * types or void.
     *
     * <p> If {@code name} denotes an array class, the component type of
     * the array class is loaded but not initialized.
     *
     * <p> For example, in an instance method the expression:
     *
     * <blockquote>
     *  {@code Class.forName("Foo")}
     * </blockquote>
     *
     * is equivalent to:
     *
     * <blockquote>
     *  {@code Class.forName("Foo", true, this.getClass().getClassLoader())}
     * </blockquote>
     *
     * Note that this method throws errors related to loading, linking or
     * initializing as specified in Sections 12.2, 12.3 and 12.4 of <em>The
     * Java Language Specification</em>.
     * Note that this method does not check whether the requested class
     * is accessible to its caller.
     *
     * <p> If the {@code loader} is {@code null}, and a security
     * manager is present, and the caller's class loader is not null, then this
     * method calls the security manager's {@code checkPermission} method
     * with a {@code RuntimePermission("getClassLoader")} permission to
     * ensure it's ok to access the bootstrap class loader.
     *
     * @param name       fully qualified name of the desired class
     * @param initialize if {@code true} the class will be initialized.
     *                   See Section 12.4 of <em>The Java Language Specification</em>.
     * @param loader     class loader from which the class must be loaded
     * @return           class object representing the desired class
     *
     * @exception LinkageError if the linkage fails
     * @exception ExceptionInInitializerError if the initialization provoked
     *            by this method fails
     * @exception ClassNotFoundException if the class cannot be located by
     *            the specified class loader
     *
     * @see       java.lang.Class#forName(String)
     * @see       java.lang.ClassLoader
     * @since     1.2
     * boolean initialize 是否对类进行初始化
     */
    @CallerSensitive
    public static Class<?> forName(String name, boolean initialize,
                                   ClassLoader loader)
        throws ClassNotFoundException
    {
        Class<?> caller = null;
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            // Reflective call to get caller class is only needed if a security manager
            // is present.  Avoid the overhead of making this call otherwise.
            caller = Reflection.getCallerClass();
            if (sun.misc.VM.isSystemDomainLoader(loader)) {
                ClassLoader ccl = ClassLoader.getClassLoader(caller);
                if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
                    sm.checkPermission(
                        SecurityConstants.GET_CLASSLOADER_PERMISSION);
                }
            }
        }
        return forName0(name, initialize, loader, caller);
    }

    /** Called after security check for system loader access checks have been made. */
    private static native Class<?> forName0(String name, boolean initialize,
                                            ClassLoader loader,
                                            Class<?> caller)
        throws ClassNotFoundException;

在使用反射的时候,Class.forName是最常用的一种方式。而Class.forName底层会指向forName0这个本地方法

参数:

(1)name:类的全限定名

(2)initialize:是否初始化这个类

(3)loader:类加载器

(4)caller:调用Class.forName所在类的Class,比如A类代码块里有Class.forName,那么caller就是A的class实例。

getConstructors

    /**
     * Returns an array containing {@code Constructor} objects reflecting
     * all the public constructors of the class represented by this
     * {@code Class} object.  An array of length 0 is returned if the
     * class has no public constructors, or if the class is an array class, or
     * if the class reflects a primitive type or void.
     *
     * Note that while this method returns an array of {@code
     * Constructor<T>} objects (that is an array of constructors from
     * this class), the return type of this method is {@code
     * Constructor<?>[]} and <em>not</em> {@code Constructor<T>[]} as
     * might be expected.  This less informative return type is
     * necessary since after being returned from this method, the
     * array could be modified to hold {@code Constructor} objects for
     * different classes, which would violate the type guarantees of
     * {@code Constructor<T>[]}.
     *
     * @return the array of {@code Constructor} objects representing the
     *         public constructors of this class
     * @throws SecurityException
     *         If a security manager, <i>s</i>, is present and
     *         the caller's class loader is not the same as or an
     *         ancestor of the class loader for the current class and
     *         invocation of {@link SecurityManager#checkPackageAccess
     *         s.checkPackageAccess()} denies access to the package
     *         of this class.
     *
     * @since JDK1.1
     * 返回构造函数组成的数据
     */
    @CallerSensitive
    public Constructor<?>[] getConstructors() throws SecurityException {
        //判断是否有访问权限
        checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
        //获取到声明的构造方法,并拷贝一份构造方法
        return copyConstructors(privateGetDeclaredConstructors(true));
    }

privateGetDeclaredConstructors()

    // Returns an array of "root" constructors. These Constructor
    // objects must NOT be propagated to the outside world, but must
    // instead be copied via ReflectionFactory.copyConstructor.
    private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) {
        //判断是否配置了useCached属性
        checkInitted();
        Constructor<T>[] res;
        //获取缓存当中的数据
        ReflectionData<T> rd = reflectionData();
        if (rd != null) {
            //返回缓存当中的构造方法 根据publicOnly决定是共有还是私有的构造方法
            res = publicOnly ? rd.publicConstructors : rd.declaredConstructors;
            if (res != null) return res;
        }
        // No cached value available; request value from VM
        if (isInterface()) {
            //直接生成一个数组长度为0的Constructor数组  因为接口没有构造方法
            @SuppressWarnings("unchecked")
            Constructor<T>[] temporaryRes = (Constructor<T>[]) new Constructor<?>[0];
            res = temporaryRes;
        } else {
            //从JVM当中读取数据
            res = getDeclaredConstructors0(publicOnly);
        }
        if (rd != null) {
            //更新缓存reflectionData当中的构造方法
            if (publicOnly) {
                rd.publicConstructors = res;
            } else {
                rd.declaredConstructors = res;
            }
        }
        return res;
    }
reflectionData
    // Lazily create and cache ReflectionData
    //创建和缓存反射获得的数据
    private ReflectionData<T> reflectionData() {
        //获取当前reflectionData
        SoftReference<ReflectionData<T>> reflectionData = this.reflectionData;
        int classRedefinedCount = this.classRedefinedCount;
        ReflectionData<T> rd;
        //如果可以使用缓存,并且缓存当中的数据不为null,而且缓存没有失效,(缓存当中redefinedCount等于classRedefinedCount的值)
        if (useCaches &&
            reflectionData != null &&
            (rd = reflectionData.get()) != null &&
            rd.redefinedCount == classRedefinedCount) {
            //直接返回缓存当中的reflectionData
            return rd;
        }
        // else no SoftReference or cleared SoftReference or stale ReflectionData
        // -> create and replace new instance
        //创建新的reflectionData,并保存到缓存当中去
        return newReflectionData(reflectionData, classRedefinedCount);
    }
newReflectionData
    private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData,
                                                int classRedefinedCount) {
        //不使用缓存,直接返回
        if (!useCaches) return null;
        //while + cas
        while (true) {
            //创建新的ReflectionData
            ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount);
            // try to CAS it...
            //更新成功,返回
            if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) {
                return rd;
            }
            // else retry
            //否则获得旧的reflectionData和classRedefinedCount的值
            oldReflectionData = this.reflectionData;
            classRedefinedCount = this.classRedefinedCount;
            //如果旧的值不为null, 并且缓存未失效,说明其他线程更新成功了
            if (oldReflectionData != null &&
                (rd = oldReflectionData.get()) != null &&
                rd.redefinedCount == classRedefinedCount) {
                //直接返回
                return rd;
            }
        }
    }

newInstance

Constructor.java

获取到Constructor之后,可以通过newInstance的方式获取到实例方法

Constructor.java
   /**
     * Uses the constructor represented by this {@code Constructor} object to
     * create and initialize a new instance of the constructor's
     * declaring class, with the specified initialization parameters.
     * Individual parameters are automatically unwrapped to match
     * primitive formal parameters, and both primitive and reference
     * parameters are subject to method invocation conversions as necessary.
     *
     * <p>If the number of formal parameters required by the underlying constructor
     * is 0, the supplied {@code initargs} array may be of length 0 or null.
     *
     * <p>If the constructor's declaring class is an inner class in a
     * non-static context, the first argument to the constructor needs
     * to be the enclosing instance; see section 15.9.3 of
     * <cite>The Java&trade; Language Specification</cite>.
     *
     * <p>If the required access and argument checks succeed and the
     * instantiation will proceed, the constructor's declaring class
     * is initialized if it has not already been initialized.
     *
     * <p>If the constructor completes normally, returns the newly
     * created and initialized instance.
     *
     * @param initargs array of objects to be passed as arguments to
     * the constructor call; values of primitive types are wrapped in
     * a wrapper object of the appropriate type (e.g. a {@code float}
     * in a {@link java.lang.Float Float})
     *
     * @return a new object created by calling the constructor
     * this object represents
     *
     * @exception IllegalAccessException    if this {@code Constructor} object
     *              is enforcing Java language access control and the underlying
     *              constructor is inaccessible.
     * @exception IllegalArgumentException  if the number of actual
     *              and formal parameters differ; if an unwrapping
     *              conversion for primitive arguments fails; or if,
     *              after possible unwrapping, a parameter value
     *              cannot be converted to the corresponding formal
     *              parameter type by a method invocation conversion; if
     *              this constructor pertains to an enum type.
     * @exception InstantiationException    if the class that declares the
     *              underlying constructor represents an abstract class.
     * @exception InvocationTargetException if the underlying constructor
     *              throws an exception.
     * @exception ExceptionInInitializerError if the initialization provoked
     *              by this method fails.
     *  获取到实例方法
     */
    @CallerSensitive
    public T newInstance(Object ... initargs)
        throws InstantiationException, IllegalAccessException,
               IllegalArgumentException, InvocationTargetException
    {
        //判断语言级别的访问权限是否被覆盖
        if (!override) {
            //没有被覆盖需要检查是否有访问权限
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                Class<?> caller = Reflection.getCallerClass();
                checkAccess(caller, clazz, null, modifiers);
            }
        }
        //判断是否为枚举类型
        if ((clazz.getModifiers() & Modifier.ENUM) != 0)
            //如果是枚举类型不能通过反射创建
            throw new IllegalArgumentException("Cannot reflectively create enum objects");
        //获取constructorAccessor
        ConstructorAccessor ca = constructorAccessor;   // read volatile
        if (ca == null) {
            //如果为null, 通过acquireConstructorAccessor获取
            ca = acquireConstructorAccessor();
        }
        //通过ConstructorAccessor创建实例对象
        @SuppressWarnings("unchecked")
        T inst = (T) ca.newInstance(initargs);
        return inst;
    }

acquireConstructorAccessor

构建ConstructorAccessor

Constructor.java 
     // NOTE that there is no synchronization used here. It is correct
    // (though not efficient) to generate more than one
    // ConstructorAccessor for a given Constructor. However, avoiding
    // synchronization will probably make the implementation more
    // scalable.
    private ConstructorAccessor acquireConstructorAccessor() {
        // First check to see if one has been created yet, and take it
        // if so.
        ConstructorAccessor tmp = null;
        if (root != null) tmp = root.getConstructorAccessor();
        if (tmp != null) {
            //先判断是否已经创建了ConstructorAccessor 如果已经创建了,直接返回获取就可以
            constructorAccessor = tmp;
        } else {
            // Otherwise fabricate one and propagate it up to the root
            //通过reflectionFactory来创建一个新的ConstructorAccessor
            tmp = reflectionFactory.newConstructorAccessor(this);
            //设置当前Class对象当中的ConstructorAccessor对象
            setConstructorAccessor(tmp);
        }

        return tmp;
    }

getDeclaredMethod

获取指定的Method对象方法

    /**
     * Returns a {@code Method} object that reflects the specified
     * declared method of the class or interface represented by this
     * {@code Class} object. The {@code name} parameter is a
     * {@code String} that specifies the simple name of the desired
     * method, and the {@code parameterTypes} parameter is an array of
     * {@code Class} objects that identify the method's formal parameter
     * types, in declared order.  If more than one method with the same
     * parameter types is declared in a class, and one of these methods has a
     * return type that is more specific than any of the others, that method is
     * returned; otherwise one of the methods is chosen arbitrarily.  If the
     * name is "&lt;init&gt;"or "&lt;clinit&gt;" a {@code NoSuchMethodException}
     * is raised.
     *
     * <p> If this {@code Class} object represents an array type, then this
     * method does not find the {@code clone()} method.
     *
     * @param name the name of the method
     * @param parameterTypes the parameter array
     * @return  the {@code Method} object for the method of this class
     *          matching the specified name and parameters
     * @throws  NoSuchMethodException if a matching method is not found.
     * @throws  NullPointerException if {@code name} is {@code null}
     * @throws  SecurityException
     *          If a security manager, <i>s</i>, is present and any of the
     *          following conditions is met:
     *
     *          <ul>
     *
     *          <li> the caller's class loader is not the same as the
     *          class loader of this class and invocation of
     *          {@link SecurityManager#checkPermission
     *          s.checkPermission} method with
     *          {@code RuntimePermission("accessDeclaredMembers")}
     *          denies access to the declared method
     *
     *          <li> the caller's class loader is not the same as or an
     *          ancestor of the class loader for the current class and
     *          invocation of {@link SecurityManager#checkPackageAccess
     *          s.checkPackageAccess()} denies access to the package
     *          of this class
     *
     *          </ul>
     *
     * @jls 8.2 Class Members
     * @jls 8.4 Method Declarations
     * @since JDK1.1
     * 获取指定的Method对象方法
     */
    @CallerSensitive
    public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {
        //判断当前method是否有访问权限
        checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
        //privateGetDeclaredMethods获取到当前所声明的所有方法
        //根据当前传递的方法名和参数类型从声明的方法中找到匹配的方法
        Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
        if (method == null) {
            throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
        }
        //返回
        return method;
    }

privateGetDeclaredMethods

    // Returns an array of "root" methods. These Method objects must NOT
    // be propagated to the outside world, but must instead be copied
    // via ReflectionFactory.copyMethod.
    //获取类中声明方法具体的实现
    //publicOnly 是否只获取public方法
    private Method[] privateGetDeclaredMethods(boolean publicOnly) {
        //等待系统内部类初始化完成,系统属性(sun.reflect.noCaches)被解析完成
        checkInitted();
        Method[] res;
        //判断当前是否有配置信息
        ReflectionData<T> rd = reflectionData();
        if (rd != null) {
            //从缓存中获取数据
            res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;
            if (res != null) return res;
        }
        // No cached value available; request value from VM
        //从JVM当中读取数据  getDeclaredMethods0(publicOnly) 使用native方式读取methods数组对象
        res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
        if (rd != null) {
            //将缓存当中的数据更新
            if (publicOnly) {
                rd.declaredPublicMethods = res;
            } else {
                rd.declaredMethods = res;
            }
        }
        return res;
    }
举报

相关推荐

0 条评论