Reflection
核心便是Class类,类图如下:
方法获取
我们以getDeclaredMethods为例:
1@CallerSensitive
2public Method[] getDeclaredMethods() throws SecurityException {
3 return copyMethods(privateGetDeclaredMethods(false));
4}
privateGetDeclaredMethods:
1private Method[] privateGetDeclaredMethods(boolean publicOnly) {
2 Method[] res;
3 ReflectionData<T> rd = reflectionData();
4 if (rd != null) {
5 res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;
6 if (res != null) return res;
7 }
8 // No cached value available; request value from VM
9 res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
10 if (rd != null) {
11 if (publicOnly) {
12 rd.declaredPublicMethods = res;
13 } else {
14 rd.declaredMethods = res;
15 }
16 }
17 return res;
18}
publicOnly为false便说明需要获取各种访问级别的方法。
缓存
为加快方法获取的性能,这里会对反射的结果进行缓存。缓存以Class内部类ReflectionData对象的形式进行保存:
1private static class ReflectionData<T> {
2 volatile Field[] declaredFields;
3 volatile Field[] publicFields;
4 volatile Method[] declaredMethods;
5 volatile Method[] publicMethods;
6 volatile Constructor<T>[] declaredConstructors;
7 volatile Constructor<T>[] publicConstructors;
8 // Intermediate results for getFields and getMethods
9 volatile Field[] declaredPublicFields;
10 volatile Method[] declaredPublicMethods;
11 volatile Class<?>[] interfaces;
12 // Value of classRedefinedCount when we created this ReflectionData instance
13 final int redefinedCount;
14 ReflectionData(int redefinedCount) {
15 this.redefinedCount = redefinedCount;
16 }
17}
reflectionData方法:
1private ReflectionData<T> reflectionData() {
2 SoftReference<ReflectionData<T>> reflectionData = this.reflectionData;
3 int classRedefinedCount = this.classRedefinedCount;
4 ReflectionData<T> rd;
5 if (useCaches && reflectionData != null && (rd = reflectionData.get()) != null &&
6 rd.redefinedCount == classRedefinedCount) {
7 return rd;
8 }
9 // else no SoftReference or cleared SoftReference or stale ReflectionData
10 // -> create and replace new instance
11 return newReflectionData(reflectionData, classRedefinedCount);
12}
与之相关的两个属性定义:
1private volatile transient SoftReference<ReflectionData<T>> reflectionData;
2// Incremented by the VM on each call to JVM TI RedefineClasses()
3// that redefines this class or a superclass.
4private volatile transient int classRedefinedCount = 0;
从这里可以看出,每次JVM对当前类或其父类重新加载时都会导致classRedefinedCount的增加。Class使用了软引用进行缓存,只要虚拟机进行Full GC,便会对软引用指向的对象进行回收,所以软引用的对象的生存周期是当前至下一次Full GC。
变量useCaches决定了是否对反射结果进行缓存,其取值由方法checkInitted决定,相关源码:
1String val = System.getProperty("sun.reflect.noCaches");
2if (val != null && val.equals("true")) {
3 useCaches = false;
4}
有意思的细节: 这里使用字符串比较判断是否为true,而不是使用Boolean.getBoolean方法,这样是为了避免Boolean类的初始化,因为JVM规范定义了对类的静态方法的调用将导致类的初始化。
注意reflectionData方法判断缓存是否有效的条件里的这一个:
1rd.redefinedCount == classRedefinedCount
这就是说,只有缓存保存的类加载次数与类保存的相一致时缓存才是有效的。
过滤
当没有缓存或缓存已失效或被回收时,便需要向JVM请求获得相关信息,这里是通过native方法getDeclaredMethods0实现,类Reflection位于sun.reflect包下,JDK这样解释其功能: 将敏感的或是JVM内部的对象(属性或方法)过滤出去。
拷贝
copyMethods实现:
1private static Method[] copyMethods(Method[] arg) {
2 Method[] out = new Method[arg.length];
3 ReflectionFactory fact = getReflectionFactory();
4 for (int i = 0; i < arg.length; i++) {
5 out[i] = fact.copyMethod(arg[i]);
6 }
7 return out;
8}
跳过复杂的调用关系,真正进行拷贝的其实就是Method的copy方法:
1Method copy() {
2 if (this.root != null)
3 throw new IllegalArgumentException("Can not copy a non-root Method");
4 Method res = new Method(clazz, name, parameterTypes, returnType,
5 exceptionTypes, modifiers, slot, signature,
6 annotations, parameterAnnotations, annotationDefault);
7 res.root = this;
8 // Might as well eagerly propagate this if already present
9 res.methodAccessor = methodAccessor;
10 return res;
11}
可以看出,每次返回的都是一个全新的Method对象,新对象的root属性指向原对象,一个Method对象及其副本共享一个methodAccessor,methodAccessor对象可以看做是对JVM相应方法的引用。
那这里为什么要进行拷贝呢?