Java基础5大机制——反射机制详解(一)

本文深入探讨Java反射机制,包括其概念、应用场景、Class类的作用,以及如何通过反射获取类的成员变量、方法和构造方法。同时,分析了Class类的内部结构和关键方法,如forName()和newInstance(),并讨论了它们的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、反射的概述

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

简而言之:在Java 中要想不通过常规手段(new Object的方式)操作一个类以及它的实例对象,必须先要获取到该类的字节码文件对象。而Java中的字节码对象就是Class类,以及该类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象.

二、反射基础

RTTI(Run-Time Type Identification)运行时类型识别。在《Thinking in Java》一书第十四章中有提到,其作用是在运行时识别一个对象的类型和类的信息。主要有两种方式:一种是“传统的”RTTI,它假定我们在编译时已经知道了所有的类型(泛型机制);另一种是“反射”机制,它允许我们在运行时发现和使用类的信息。

反射就是把java类中的各种成分:成员变量,构造方法,普通方法,方法和变量的修饰符等等,映射成一个个的Java对象。

例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。

这里我们首先需要理解 Class类,以及类的加载机制; 然后基于此我们如何通过反射获取Class类以及类中的成员变量、方法、构造方法等。

三、Class类介绍

Class类,Class类也是一个实实在在的类,存在于JDK的java.lang包中。Class类的实例表示java应用运行时的类(class and enum)或接口(interface and annotation)

每个java类运行时都在JVM里表现为一个class对象,可通过如下三种方法获取class对象

  1. 可通过类名.class
  2. 实例对象.getClass()
  3. Class.forName("类名")

数组同样也被映射为Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本类型boolean,byte,char,short,int,long,float,double和关键字void同样表现为 Class 对象。

顺便说一下:如何看源码。

JDK源码是编写者智慧结晶,是众多开发者,合力的结果。里面的每一段代码,写出来都是有意义的,不是说想怎么写就怎么写。都是这些大佬,经过深思熟虑想出来的方式方法。一定程度上都是考虑到了各种因素:兼容性,可读性,性能,组织结构,所以不要质疑大佬写的代码。

我们要学习的是大佬写代码的思路和方式方法和解决问题的能力。通过阅读源码,更好的了解Java的性能和机制。

如何看源码:

        第一步:看类的继承结构,以及该类本身的类型以及修饰符,实现了哪些接口,具备哪些功能,有没有泛型。

        第二步:看静态代码块,是否有提前加载的内容。看构造方法,是否有私有的构造方法。以及该类的实例化模式

        第三步:看类的成员变量,有哪些数学,分别代表了什么行为,用于哪些方法

        第四步:看方法,读注释,看返回值。方法的修饰类型,返回值,调用方式,是否支持泛型

Class源码分析

1、Class类继承结构和修饰类型

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

}

到这我们也就可以得出以下几点信息:

首先Class的结构上:实现了四个接口,直接说明Class类具有四种能力。分别是:

        1、java 序列化接口 Serializable 支持序列化

        2、GenericDeclaration 泛型通用接口里面只有一个方法


//返回定义泛型对象时顺序声明的泛型对象的数组,这些对象表示由此GenericDeclaration对象表示
 public TypeVariable<?>[] getTypeParameters();

        3、 Type 泛型描述接口

//返回制定反响的具体信息和参数的类型名称
    default String getTypeName() {
        return toString();
    }

        4、AnnotatedElement 注解接口:实现这个接口(AnnotatedElement)的对象代表了在当前JVM中的一个“被注解元素”(可以是Class,Method,Field,Constructor,Package等)。

        所以Class类具有的能力:可以被序列化,可以获取类的注解,泛型对象以及对应的泛型参数。

其次:Class类通被final修饰说明:

        1、Class类被初始化后,在内存里的地址,不能够被修改,但是其值不能修改并不意味着其所指向的对象不能修改。

        2、表示该类是无法被任何其他类继承的,意味着此类在一个继承树中是一个叶子类,并且此类的设计已被认为很完美而不需要进行修改或扩展。(大佬们就是这么自信)

2、成员变量

  1、常量


    //定义注解类型的常量
    private static final int ANNOTATION = 0x00002000;
    
    //定义枚举类型的常量
    private static final int ENUM      = 0x00004000;
    
    //定义复合类的常量
    private static final int SYNTHETIC = 0x00001000;

0x代表该常量是使用16进制进行解析,三个常量是用于与类的修饰类型做&操作得到具体类型的判断

// 获取类或者接口的修饰类型:
// public,protected,private,final,static,abstract,interface
public native int getModifiers();


//返回 boolean :如果是注解类型返回true
public boolean isAnnotation() {
        return (getModifiers() & ANNOTATION) != 0;
    }

//返回 boolean :如果是复合类返回true
public boolean isSynthetic() {
        return (getModifiers() & SYNTHETIC) != 0;
    }

//枚举判断特殊一点,父类要继承ENUM类,修饰符是枚举修饰符才算是枚举
public boolean isEnum() {
        // An enum must both directly extend java.lang.Enum and have
        // the ENUM bit set; classes for specialized enum constants
        // don't do the former.
        return (this.getModifiers() & ENUM) != 0 &&
        this.getSuperclass() == java.lang.Enum.class;
    }

有些小伙伴可能会对复合类有疑问?这边引用stackFlow大佬的回答:

回答:Java具有在运行期间动态生成字节码大的能力。这些被动态生成的类就被称之为复合类或者动态代理。比如java通过proxy包下的方法实现的类。

比如:其他开源库(例如 CGLIB 和 ASM)也提供生成复合类,并且比 JRE 提供的库更强大。 合成类被 AOP(面向方面​​编程)库(如 Spring AOP 和 AspectJ)以及 ORM 库(如 Hibernate)所使用。

复合类大佬回答

2、引用类型的普通变量

    // 不会被序列化的构造函数对象缓存,而且对于执行线程,被修改时是可见的
    private volatile transient Constructor<T> cachedConstructor;
    
    //不会被序列化的Class对象,当构造函数对象缓存被修改时,需要重新进行赋值
    private volatile transient Class<?> newInstanceCallerCache;

    //缓存该类的全类名,避免多次调用Java虚拟机
    private transient String name;

    //类加载器 不是由私有的构造函数初始化的,而是由虚拟机进行初始化
    private final ClassLoader classLoader;

    //java 类加载时安全校验机制
    private static java.security.ProtectionDomain allPermDomain;
  
    //是否使用缓存 :有确定的反射结果,才会进行缓存
    private static boolean useCaches = true;
    
    //反射数据的软引用,且不会被序列化
    private volatile transient SoftReference<ReflectionData<T>> reflectionData;

    //调用JVM TI RedefineClasses()方法,计数器。(重新定义该类或者父类)
    private volatile transient int classRedefinedCount = 0;
    
    // 生成类的相关信息保存,懒加载完成
    private volatile transient ClassRepository genericInfo;
    
    //类的序列化流工具
    private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];

    //反射工厂,提供反射相关操作
    private static ReflectionFactory reflectionFactory;
    
    //是否可以查询系统属性 boolean类型
    private static boolean initted = false;

    //获取枚举类中的元素 数组类型
    private volatile transient T[] enumConstants = null;

    //生成枚举类型的Map K:全类名字,T:枚举类型
    private volatile transient Map<String, T> enumConstantDirectory = null;

    //注解类型数据
    private volatile transient AnnotationData annotationData;

    //注解类型
    private volatile transient AnnotationType annotationType;

    //该字节码类型的备份,由classValueMap 存储
    transient ClassValue.ClassValueMap classValueMap;

从修饰符可以看出Class类中用的最多便是 volatile 和 transient

volatile:避免指令重排序,变量被修改时对所有线程可见。

transient:保证该成员变量不被序列化,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。 

3、构造方法和成员方法

3.1、构造方法

    // C++/C 写的注册方法
    private static native void registerNatives();


    // 类加载器由JVM初始化,并且这个字段会从反射中过滤,如果想通过getDeclaredField获取类加载器会抛出NoSuchFieldException
    private final ClassLoader classLoader;
    
    // 确定要一点初始化的过程,应该是初始化了类加载器的。
    static {
        registerNatives();
    }


   //私有构造器,只有JVM才能调用和创建Class对象,并且这个构造方法是先于对象的构造方法产生的。
    private Class(ClassLoader loader) {
        classLoader = loader;
    }

私有构造方法说明:Class 源代码中的注释指出,初始化值,使JIT知道 classLoader 字段不为空。

 JIT编译(just-in-time compilation)狭义来说是当某段代码即将第一次被执行时进行编译,因而叫“即时编译”

 大佬的回答:java - JIT optimization preventing techniques - Stack Overflow

3.2、核心成员方法

  • 再来看看 Class类的方法
方法名说明
forName()

(1)获取Class对象的一个引用,但引用的类还没有加载(该类的第一个对象没有生成)就加载了这个类。

(2)为了产生Class引用,forName()立即就进行了初始化。

Object-getClass()获取Class对象的一个引用,返回表示该对象的实际类型的Class引用。
getName()取全限定的类名(包括包名),即类的完整名字。
getSimpleName()获取类名(不包括包名)
getCanonicalName()获取全限定的类名(包括包名)
isInterface()判断Class对象是否是表示一个接口
getInterfaces()返回Class对象数组,表示Class对象所引用的类所实现的所有接口。
getSupercalss()返回Class对象,表示Class对象所引用的类所继承的直接基类。应用该方法可在运行时发现一个对象完整的继承结构。
newInstance()返回一个Oject对象,是实现“虚拟构造器”的一种途径。使用该方法创建的类,必须带有无参的构造器。
getFields()获得某个类的所有的公共(public)的字段,包括继承自父类的所有公共字段。 类似的还有getMethods和getConstructors。
getDeclaredFields获得某个类的自己声明的字段,即包括public、private和proteced,默认但是不包括父类声明的任何字段。类似的还有getDeclaredMethods和getDeclaredConstructors。

由于大部分方法都是Native方法,这里我们选取重点的方法说明:

方法一:forName(Sting name)

说明:通过全限定类名,来获取对应该类的字节码对象:Class<T> 其中T:全限定类名类型,可以是类,接口,枚举。


// 通过全限定类名加载对应的Class<T> 对象
@CallerSensitive
public static Class<?> forName(String className)
                throws ClassNotFoundException {
        //返回调用此方法的调用者Class对象
        Class<?> caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }


//实例化Class类型对象
//name:全限定类名
//initialize:是否需要立即初始化
//loader:类加载器
//caller: 调用者class对象
private static native Class<?> forName0(String name, boolean initialize,
                                            ClassLoader loader,
                                            Class<?> caller)
        throws ClassNotFoundException;

实际调用的是forName0()方法,

其中令人疑惑的是Reflection.getCallerClass()方法和@CallerSensitive注解

Reflection.getCallerClass():返回调用此方法的方法的调用者的类,忽略与java.lang.reflect.Method.invoke()相关联的框架及其实现

@CallerSensitive
public static native Class<?> getCallerClass();

主要有两个目的:

        1、 @CallerSensitive注解:用来找到真正发起反射请求的类的,保证该类是符合JVM的安全策略,解决通过反射导致的安全漏洞。

        这个漏洞简单说:避免多重反射来提升类的权限。

这个注解是为了配合Reflection.getCallerClass()用的,Reflection.getCallerClass()作用是返回它的调用者,但是要使用Reflection.getCallerClass()就必须满足两个条件。

第一个条件使用他的类必须是启动类或者拓展类指定路径上的类。

第二个是必须加上这个注解。也就是说,如果用户想使用Reflection.getCallerClass(),除了加上这个注解外,还需要指定自己定义的类位于启动类或者拓展类的类路径下,即需要使用-Xbootclasspath参数去指定

        2、获取到调用该方法的源头类的Class,从而获取到对应的类加载器。 

具体介绍Reflection.getCallerClass()的文章链接,这里提供两个

1、Reflection.getCallerClass()-解释

2、Reflection.getCallerClass()-解释

阅读完这两篇文章,应该就明白了。

简单来说:

反射相关的类是有很高权限的,而在 我->反射1->反射2 这样的调用链上,反射2检查权限时看到的是反射1的类,这就被欺骗了,导致安全漏洞。使用CallerSensitive后,getCallerClass不再用固定深度去寻找actual caller(“我”),而是把所有跟反射相关的接口方法都标注上CallerSensitive,搜索时凡看到该注解都直接跳过,这样就有效解决了前面举例的问题

 核心方法二  public T newInstance()

返回泛型,该泛型,是由forName(String name) 方法中传入的全限定类名指定

源码:

 @CallerSensitive
    public T newInstance()
        throws InstantiationException, IllegalAccessException
    {
        //校验Java安全管理器,不为null
        if (System.getSecurityManager() != null) {
            //校验调用该类的权限能否通过
            checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
        }

       //注意:以下代码可能不是严格的符合目前Java的内存模型(1.8)。

        // 构造函数从这里开始
        if (cachedConstructor == null) {
            if (this == Class.class) {
                throw new IllegalAccessException(
                    "Can not call newInstance() on the Class for java.lang.Class"
                );
            }
            try {
                Class<?>[] empty = {};
                final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedAction<Void>() {
                        public Void run() {
                                c.setAccessible(true);
                                return null;
                            }
                        });
                cachedConstructor = c;
            } catch (NoSuchMethodException e) {
                throw (InstantiationException)
                    new InstantiationException(getName()).initCause(e);
            }
        }
        Constructor<T> tmpConstructor = cachedConstructor;
        // Security check (same as in java.lang.reflect.Constructor)
        int modifiers = tmpConstructor.getModifiers();
        if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
            Class<?> caller = Reflection.getCallerClass();
            if (newInstanceCallerCache != caller) {
                Reflection.ensureMemberAccess(caller, this, null, modifiers);
                newInstanceCallerCache = caller;
            }
        }
        

        // 运行构造函数
        try {
            // 默认调用的是无参的构造函数
            return tmpConstructor.newInstance((Object[])null);
        } catch (InvocationTargetException e) {
            Unsafe.getUnsafe().throwException(e.getTargetException());
            return null;
        }
    }

 代码流程:

        1、同样也有@CallerSensitive注解,不在赘述

        2、获取java安全管理器:System.getSecurityManager()

            Java安全管理器解释

此方法的返回类型为SecurityManager ,仅在当前为当前接口建立安全管理器时才返回安全管理器,而在没有为当前应用程序建立安全管理器时返回null。

        3、权限校验检查

private void checkMemberAccess(int which, Class<?> caller, boolean checkProxyInterfaces)

 参数1:which:int :常量,可以获取的权限类型

 参数2:  caller:Class<?> 调用类的字节码对象

 参数3:  checkProxyInterfaces:boolean 是否校验代理接口

 checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);

 入参:Member.PUBLIC,Reflection.getCallerClass(),false

/*
Member 是一个接口,这个接口定义了单个成员(字段或方法)或构造函数的标识。
*/
public interface Member {

    //可以访问类或者接口中通过 public 修饰的成员信息,包括继承的成员
    public static final int PUBLIC = 0;


    // 定义了类或者接口中声明的成员信息,不包括继承的成员
    public static final int DECLARED = 1;

    
    // 获取声明类或者接口的字节码对象
    public Class<?> getDeclaringClass();

    //返回成员的名称 eg:成员变量的名字,成员方法,构造函数
    public String getName();

    //返回成员的修饰符
    public int getModifiers();

    //判断该成员是否是动态生成的。 true:动态生成。
    public boolean isSynthetic();
}

 checkMemberAccess() 具体实现

// 校验成员的权限 
private void checkMemberAccess(int which, Class<?> caller, boolean checkProxyInterfaces) {
        
        //获取安全管理器
        final SecurityManager s = System.getSecurityManager();
        if (s != null) {
            //获取调用类的类加载器
            final ClassLoader ccl = ClassLoader.getClassLoader(caller);
            //返回Class类的类加载器
            final ClassLoader cl = getClassLoader0();
            //如果调用成员的权限不是public
            if (which != Member.PUBLIC) {
                //两者的类加载器不一致
                if (ccl != cl) {
               //校验权限是否是获取声明成员权限                 
               s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
                }
            }
            //校验包的权限
            this.checkPackageAccess(ccl, checkProxyInterfaces);
        }
    }

//Class类初始化的类加载器
ClassLoader getClassLoader0() { return classLoader; }

// accessDeclaredMembers:获取声明成员权限
public static final RuntimePermission CHECK_MEMBER_ACCESS_PERMISSION = new RuntimePermission("accessDeclaredMembers");


//检验包权限
private void checkPackageAccess(final ClassLoader ccl, boolean checkProxyInterfaces) {
        final SecurityManager s = System.getSecurityManager();
        if (s != null) {
            final ClassLoader cl = getClassLoader0();
            
            //通过反射工具类校验包的权限
            if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
                String name = this.getName();
                int i = name.lastIndexOf('.');
                if (i != -1) {
                    //获取包名
                    String pkg = name.substring(0, i);
                      if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) {
                        s.checkPackageAccess(pkg);
                    }
                }
            }
            if (checkProxyInterfaces && Proxy.isProxyClass(this)) {
                ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces());
            }
        }
    }

//校验包权限的方法
  public static boolean needsPackageAccessCheck(ClassLoader var0, ClassLoader var1) {
     // 源类加载器 不为 null ,目标类加载器不等于源类加载器 
     if (var0 != null && var0 != var1) {
            //目标类加载器 等于 null
            if (var1 == null) {
                //说明使用的都是同一个类加载器
                return true;
            } else {
                //判断父类是否使用的是同一个类加载器
                return !isAncestor(var0, var1);
            }
        } else {
            return false;
        }
    }


//校验父加载器是否一致
private static boolean isAncestor(ClassLoader var0, ClassLoader var1) {
        ClassLoader var2 = var1;

        do {
            //目标类的类加载器的父类
            var2 = var2.getParent();
            if (var0 == var2) {
                return true;
            }
        } while(var2 != null);

        return false;
    }

         4、核心逻辑

    // 构造函数对象缓存
    private volatile transient Constructor<T> cachedConstructor;
    // 字节码对象缓存
    private volatile transient Class<?>       newInstanceCallerCache; 

          

        // 判断是否有缓存的构造函数
        if (cachedConstructor == null) {
            // 如果是Class类本身
            if (this == Class.class) {
               // 抛出不能实例化Class类的异常
                throw new IllegalAccessException(
                    "Can not call newInstance() on the Class for java.lang.Class"
                );
            }
            try {
               
                Class<?>[] empty = {};
                //核心方法,获取构造函数
                final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
                //安全校验
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedAction<Void>() {
                        public Void run() {
                                c.setAccessible(true);
                                return null;
                            }
                        });
                //缓存构造函数对象
                cachedConstructor = c;
            } catch (NoSuchMethodException e) {
                throw (InstantiationException)
                    new InstantiationException(getName()).initCause(e);
            }
        }
        
        //获取对应构造函数对象
        Constructor<T> tmpConstructor = cachedConstructor;

        //获取构造函数的权限修饰符
        int modifiers = tmpConstructor.getModifiers();
       
        //校验构造函数的权限是否是 public
        if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
            // 获取调用类的字节码对象
            Class<?> caller = Reflection.getCallerClass();
            if (newInstanceCallerCache != caller) {
                // 成员权限的校验
                Reflection.ensureMemberAccess(caller, this, null, modifiers);
                // 缓存调用类的字节码对象
                newInstanceCallerCache = caller;
            }
        }

其中:

Class<?>[] empty = {};
//核心方法,获取构造函数
final Constructor<T> c = getConstructor0(empty, Member.DECLARED);

注意到 empty是空的Class<?> 数组

//参数1: 字节码对象数组
//参数2: 权限标识常量  
private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
                                        int which) throws NoSuchMethodException
    {
        //获取构造方法,不止一个,用数组表示,并且为public的构造方法
        Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
        //匹配空参的构造方法
        for (Constructor<T> constructor : constructors) {
            if (arrayContentsEq(parameterTypes,
                                constructor.getParameterTypes())) {
                return getReflectionFactory().copyConstructor(constructor);
            }
        }
        // 没有获取到,则返回没有该方法异常
        throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
    }

核心方法 privateGetDeclaredConstructors(boolean publicOnly)

用于获取public修饰的构造方法

 private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) {
        checkInitted();
        Constructor<T>[] res;
        //获取反射得到数据
        ReflectionData<T> rd = reflectionData();

        if (rd != null) {
            res = publicOnly ? rd.publicConstructors : rd.declaredConstructors;
            if (res != null) return res;
        }

        //如果是接口
        if (isInterface()) {
            @SuppressWarnings("unchecked")
            Constructor<T>[] temporaryRes = (Constructor<T>[]) new Constructor<?>[0];
            res = temporaryRes;
        } else {
            res = getDeclaredConstructors0(publicOnly);
        }
        if (rd != null) {
            if (publicOnly) {
                rd.publicConstructors = res;
            } else {
                rd.declaredConstructors = res;
            }
        }
        return res;
    }
  1. checkInitted() 来判断是否配置了useCached属性,通过sun.reflect.noCaches来配置,如果配置的话,将useCached改为配置的属性
  2. reflectionData()获取缓存当中的数据,如果缓存当中有数据,直接返回缓存当中的构造方法
  3. 如果缓存当中没有数据,就从JVM当中读取数据
  4. 如果是接口类型,直接生成一个数组长度为0的Constructor数组,因为接口没有构造方法
  5. 如果不是接口类型,从JVM当中获取getDeclaredConstructors0 是native方法
  6. 最后更新缓存reflectionData当中的构造方法

接下来,我们来看下reflectionData()方法,如何获取缓存数据,主要是延迟创建,并缓存数据

  private ReflectionData<T> reflectionData() {
        SoftReference<ReflectionData<T>> reflectionData = this.reflectionData;
        int classRedefinedCount = this.classRedefinedCount;
        ReflectionData<T> rd;
        if (useCaches &&
            reflectionData != null &&
            (rd = reflectionData.get()) != null &&
            rd.redefinedCount == classRedefinedCount) {
            return rd;
        }
        // else no SoftReference or cleared SoftReference or stale ReflectionData
        // -> create and replace new instance
        return newReflectionData(reflectionData, classRedefinedCount);
    }
  1. 首先获取当前reflectionData
  2. 如果可以使用缓存,并且缓存当中的数据不为null,而且缓存没有失效,(缓存当中redefinedCount等于classRedefinedCount的值),直接返回缓存当中的reflectionData
  3. 如果以上都不是的话,就创建新的reflectionData,并保存到缓存当中去

我们来看下newReflectionData方法的实现

 private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData,
                                                int classRedefinedCount) {
        if (!useCaches) return null;

        while (true) {
            ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount);
            // 使用CAS 进行更新
            if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) {
                return rd;
            }
            // 进行重试
            oldReflectionData = this.reflectionData;
            classRedefinedCount = this.classRedefinedCount;
            if (oldReflectionData != null &&
                (rd = oldReflectionData.get()) != null &&
                rd.redefinedCount == classRedefinedCount) {
                return rd;
            }
        }
    }
  1. 首先,还是判断是否使用缓存,如果不使用,直接返回
  2. 使用while+CAS方式更新数据,创建一个新的ReflectionData,如果更新成功直接返回,否则进入3
  3. 获取到旧的reflectionData和classRedefinedCount的值,如果旧的值不为null, 并且缓存未失效,说明其他线程更新成功了,直接返回

4、Class对象小结

 一旦类被加载了到了内存中,那么不论通过哪种方式获得该类的Class对象,它们返回的都是指向同一个java堆地址上的Class引用。jvm不会创建两个相同类型的Class对象

其实对于任意一个Class对象,都需要由它的类加载器和这个类本身一同确定其在就Java虚拟机中的唯一性,也就是说,即使两个Class对象来源于同一个Class文件,只要加载它们的类加载器不同,那这两个Class对象就必定不相等。这里的“相等”包括了代表类的Class对象的equals()、isAssignableFrom()、isInstance()等方法的返回结果,也包括了使用instanceof关键字对对象所属关系的判定结果。所以在java虚拟机中使用双亲委派模型来组织类加载器之间的关系,来保证Class对象的唯一性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值