代码片段:
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 区满,导致永久区溢出,