Java反射机制(二)—— 深入JDK了解反射(JDK1.8)

在这里插入图片描述
《Java反射机制(一)—— 使用反射》一文中我们提到,在类的初始化阶段会创建对应类的一个Class对象,Class对象里还缓存了该类的所有Constructor对象、Method对象、Filed对象。这个初始化阶段是在JDK底层以C语言实现的,有兴趣可以自行查看。本文只对反射机制是如何使用Class对象实现实例创建、方法调用、属性访问进行说明。

1.反射创建对象的过程

1.1反射获取Constructor对象的过程

反射创建一个类的对象是从获取该类的Constructor(构造器)对象开始的。Class对象获取特定构造函数对象的方法是getDeclaredConstructor(Class<?>… parameterTypes) 。

JDK源码
/*Class*/
	@CallerSensitive
    public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {
   
        checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
        return getConstructor0(parameterTypes, Member.DECLARED);
    }
	
    private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
                                        int which) throws NoSuchMethodException
    {
   
        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));
    }

从上面两个方法不难看出,要获取目标Constructor对象分为两步,获取Class对象的所有构造器对象根据参数类型数组获取到特定的构造器对象

获取所有构造器对象的方法是privateGetDeclaredConstructors,在该方法中,会先试图获取Class对象在类初始化阶段就缓存的该类的所有Constructor对象,那这个缓存在什么位置呢,这个缓存就是Class的属性private volatile transient SoftReference<ReflectionData> reflectionData。这个属性的类型是SoftReference(软引用),所谓软引用就是在资源紧张的情况下GC会进行回收,这就可能导致缓存丢失。SoftReference的泛型是ReflectionData,ReflectionData就是缓存数据的真正格式。我们来看一下ReflectionData是怎么缓存数据的。

JDK源码
/*Class$ReflectionData*/
	private static class ReflectionData<T> {
   
        volatile Field[] declaredFields;
        volatile Field[] publicFields;
        volatile Method[] declaredMethods;
        volatile Method[] publicMethods;
        volatile Constructor<T>[] declaredConstructors;
        volatile Constructor<T>[] publicConstructors;
        // Intermediate results for getFields and getMethods
        volatile Field[] declaredPublicFields;
        volatile Method[] declaredPublicMethods;
        volatile Class<?>[] interfaces;

        // Value of classRedefinedCount when we created this ReflectionData instance
        final int redefinedCount;

        ReflectionData(int redefinedCount) {
   
            this.redefinedCount = redefinedCount;
        }
    }

ReflectionData用数据的形式,将所有的Constructor、Method、Field对象存储下来供反射进行使用。

在新版本的JDK中对该缓存进行了优化,放弃使用ReflectionData存储,而是在Class中直接将Constructor、Method、Field数组放进软引用中作为缓存。这样就将缓存分散,当资源紧张时,不会一次全部被GC回收

了解了Class对象如何缓存Constructor,下面我们就来看privateGetDeclaredConstructors方法的源码。

JDK源码
	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;
        }
        // No cached value available; request value from VM
        if (isInterface()) {
   
            @SuppressWarnings("unchecked")
            Constructor<T>[] temporaryRes = (Constructor<T
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值