反射的原理粗略分析

 

代码片段:

     Method[] method = Pow3.class.getDeclaredMethods();

method[0].invoke(new Pow3(), 1);

此段代码通过反射获取类所定义的方法,具体流程是:通过class 的 getDeclaredMethods 方法获取类的定义的方法,

   @CallerSensitive
    public Method[] getDeclaredMethods() throws SecurityException {
        // be very careful not to change the stack depth of this
        // checkMemberAccess call for security reasons
        // see java.lang.SecurityManager.checkMemberAccess
        checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
        return copyMethods(privateGetDeclaredMethods(false));
    }

 主要逻辑在privateGetDeclaredMethods方法和copyMethods 方法中现在咱们来一个个分析该方法

 private Method[] privateGetDeclaredMethods(boolean publicOnly) {
        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
        res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
        if (rd != null) {
            if (publicOnly) {
                rd.declaredPublicMethods = res;
            } else {
                rd.declaredMethods = res;
            }
        }
        return res;
    }

  此方法中有个ReflectionData 数据结构,是存放反射的类相关的方法,属性信息

   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;
        // Value of classRedefinedCount when we created this ReflectionData instance
        final int redefinedCount;

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

 

 //获取反射属性的列表
        ReflectionData<T> rd = reflectionData();

 

 

 // Lazily create and cache ReflectionData
    private ReflectionData<T> reflectionData() {
      //先从缓存中取 并放到软引用中,这样有利于在内存不足的情况下jvm 回收
        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
        // -> 如果缓存中没有从VM里面拿
        return newReflectionData(reflectionData, classRedefinedCount);
    }

 

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

        while (true) {
            ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount);
            // 通过cas 算法,从vm 中拿取数据
            if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) {
                return rd;
            }
            // else retry
            oldReflectionData = this.reflectionData;
            classRedefinedCount = this.classRedefinedCount;
            if (oldReflectionData != null &&
                (rd = oldReflectionData.get()) != null &&
                rd.redefinedCount == classRedefinedCount) {
                return rd;
            }
        }
    }

   这个是读取反射对象的大概过程,接下来分析copyMethods 

  private static Method[] copyMethods(Method[] arg) {
        Method[] out = new Method[arg.length];
        ReflectionFactory fact = getReflectionFactory();
        for (int i = 0; i < arg.length; i++) {
            out[i] = fact.copyMethod(arg[i]);
        }
        return out;
    }

 fact.copyMethod 方法最终调用的是method 的copy 所以说。通过反射获取method 每次都是生成一个对象的拷贝,是一个新的method 对象,

   Method copy() {
        // This routine enables sharing of MethodAccessor objects
        // among Method objects which refer to the same underlying
        // method in the VM. (All of this contortion is only necessary
        // because of the "accessibility" bit in AccessibleObject,
        // which implicitly requires that new java.lang.reflect
        // objects be fabricated for each reflective call on Class
        // objects.)
        Method res = new Method(clazz, name, parameterTypes, returnType,
                                exceptionTypes, modifiers, slot, signature,
                                annotations, parameterAnnotations, annotationDefault);
        res.root = this;
        // Might as well eagerly propagate this if already present
        res.methodAccessor = methodAccessor;
        return res;
    }

   其实对method 的方法调用最终是methodAccessor的invoke 调用 ,也是委托给MethodAccessorImpl 的invoke 调用

 public Object invoke(Object paramObject, Object[] paramArrayOfObject)
   throws IllegalArgumentException, InvocationTargetException
 {
     return this.delegate.invoke(paramObject, paramArrayOfObject);
 }

 再委托给NativeMethodAccessorImpl 的invoke 方法

 

 public Object invoke(Object paramObject, Object[] paramArrayOfObject)
    throws IllegalArgumentException, InvocationTargetException
 {
    if (++this.numInvocations > ReflectionFactory.inflationThreshold()) {
    MethodAccessorImpl localMethodAccessorImpl = (MethodAccessorImpl)new MethodAccessorGenerator().generateMethod(this.method.getDeclaringClass(), this.method.getName(), this.method.getParameterTypes(), this.method.getReturnType(), this.method.getExceptionTypes(), this.method.getModifiers());

     this.parent.setDelegate(localMethodAccessorImpl);
     }
    
    return invoke0(this.method, paramObject, paramArrayOfObject);
   }

此段逻辑是当判断 numInvocations>15次调用会生成MethodAccessorImplXXX字节码,如果小于15次就直接调用原生的private static native Object invoke0(Method paramMethod, Object paramObject, Object[] paramArrayOfObject) 方法进行方法的调用。 需要注意的是,由于numInvocations 不是线程安全的。所以在高并发的情况下。会生成很多无用的类。如果并发1000个,会有999个是无用的,会增加perm 区满,导致永久区溢出,

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值