从源码中浅析Java反射原理

何为反射

Oracle 的官方文档中是这么解释反射的:

“Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions. The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.”

具体而言,反射 (Reflection) 提供了一种在程序运行时动态获取 Class 方法、属性、接口等内部信息的机制。通过反射可以让在程序运行期实例化对象、调用方法、获取属性,即使方法或属性是 private 的也可以通过反射机制调用。

反射原理

篇幅和精力有限,只看了获取 Class 、获取与调用 Method 和获取 Field 的源码。

反射获取 Class 原理(Class.forName()方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
@CallerSensitive
public static Class<?> forName(String className) throws ClassNotFoundException {
// 通过反射获取调用forName()方法的类caller
Class<?> caller = Reflection.getCallerClass();
// 根据caller获取当前的classLoader,继续调用forName0()方法
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

// forName0()是一个native方法,可以获取指定的class信息
private static native Class<?> forName0(String name, boolean initialize,
ClassLoader loader,
Class<?> caller)
throws ClassNotFoundException;

反射获取 Method 原理(getDeclaredMethod()方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
// 检查权限
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
// 先调用privateGetDeclaredMethods()方法,得到目标类的所有的Method
// 然后调用searchMethods()方法,根据Method的名字和参数找出符合条件的Method
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
}
return method;
}

// 从缓存或JVM中获取目标Class中的所有方法
private Method[] privateGetDeclaredMethods(boolean publicOnly) {
checkInitted();
Method[] res;
// 调用reflectionData()方法获取reflectionData
ReflectionData<T> rd = reflectionData();
// 如果reflectionData不为空
if (rd != null) {
// 尝试获取reflectionData中的方法属性
// publicOnly 为true则返回所有public方法,否则返回所有方法
res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;
if (res != null) return res;
}
// No cached value available; request value from VM
// if (rd == null)的情况,没有缓存,就从JVM中获取
res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
// 将获取到的Method[]赋给reflectionData,这样下次调用该方法时就有缓存了
if (rd != null) {
if (publicOnly) {
rd.declaredPublicMethods = res;
} else {
rd.declaredMethods = res;
}
}
return res;
}

// 以Lazily的方式创建并缓存ReflectionData
// Lazily create and cache ReflectionData
private ReflectionData<T> reflectionData() {
// ReflectionData这个数据结构存放了从JVM中读取到的信息
// 弱引用类型,可能会在内存不足的时候被 GC 清理
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;
}
// 如果reflectionData被GC回收后,就会通过newReflectionData()方法重新创建ReflectionData
// else no SoftReference or cleared SoftReference or stale ReflectionData
// -> create and replace new instance
return newReflectionData(reflectionData, classRedefinedCount);
}

// 可以看出ReflectionData中存放了Class的内部信息,包括方法、属性、构造器、接口等
// reflection data that might get invalidated when JVM TI RedefineClasses() is called
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;
}
}

// 通过上述方法就可以得到目标Class的所有方法列表
// 回到getDeclaredMethod()方法中,接着通过searchMethods()方法来找出符合条件的方法
private static Method searchMethods(Method[] methods,
String name,
Class<?>[] parameterTypes)
{
Method res = null;
// intern()方法用来返回常量池中的指定字符串,如果常量池中已经存在该字符串,则直接返回常量池中该对象的引用;否则,在常量池中加入该字符串,然后返回引用
String internedName = name.intern();
// 遍历所有方法
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
// 查找符合条件的方法
// 具体查找的原则是最优匹配
if (m.getName() == internedName
&& arrayContentsEq(parameterTypes, m.getParameterTypes())
&& (res == null
|| res.getReturnType().isAssignableFrom(m.getReturnType())))
res = m;
}
// 如果找到符合条件的方法,复制一份返回
// 所次每次调用getDeclaredMethod()方法返回的Method其实都是一个新的对象
return (res == null ? res : getReflectionFactory().copyMethod(res));
}

反射调用 Method 原理(invoke()方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
@CallerSensitive
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
// 检查调用invoke()方法类的权限
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}

// 可以看出真正的invoke操作是通过这个MethodAccessor来完成的
// 在第一次时调用invoke()方法时需要调用acquireMethodAccessor()方法创建一个新的MethodAccessor对象
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}

// MethodAccessor是一个接口,需要实现invoke()方法
public interface MethodAccessor {
Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException;
}

// NOTE that there is no synchronization used here. It is correct
// (though not efficient) to generate more than one MethodAccessor
// for a given Method. However, avoiding synchronization will
// probably make the implementation more scalable.
private MethodAccessor acquireMethodAccessor() {
// 检查一下MethodAccessor是否已经被创建了
// First check to see if one has been created yet, and take it
// if so
MethodAccessor tmp = null;
if (root != null) tmp = root.getMethodAccessor();
// 如果缓存存在就直接存入methodAccessor
if (tmp != null) {
methodAccessor = tmp;
// 否则调用ReflectionFactory的newMethodAccessor()方法创建新的MethodAccessor
// 新的MethodAccessor会实现具体的invoke()方法
// 然后再存入MethodAccessor
} else {
// Otherwise fabricate one and propagate it up to the root
tmp = reflectionFactory.newMethodAccessor(this);
setMethodAccessor(tmp);
}
return tmp;
}

public MethodAccessor newMethodAccessor(Method var1) {
checkInitted();
if (noInflation && !ReflectUtil.isVMAnonymousClass(var1.getDeclaringClass())) {
return (new MethodAccessorGenerator()).generateMethod(var1.getDeclaringClass(), var1.getName(), var1.getParameterTypes(), var1.getReturnType(), var1.getExceptionTypes(), var1.getModifiers());
} else {
NativeMethodAccessorImpl var2 = new NativeMethodAccessorImpl(var1);
// var3是一个代理对象,负责调用被代理对象var2的invoke方法
// 即最后执行的是NativeMethodAccessorImpl.invoke()方法
DelegatingMethodAccessorImpl var3 = new DelegatingMethodAccessorImpl(var2);
var2.setParent(var3);
return var3;
}
}

// NativeMethodAccessorImpl中实现的invoke()方法
public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
if (++this.numInvocations > ReflectionFactory.inflationThreshold() && !ReflectUtil.isVMAnonymousClass(this.method.getDeclaringClass())) {
MethodAccessorImpl var3 = (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(var3);
}
// 实际上是调用invoke0()方法
return invoke0(this.method, var1, var2);
}

// 接着来看invoke0()方法,可以看出这是一个native方法
// 至此整个反射执行方法的过程就分析完了,真的是绕啊
private static native Object invoke0(Method var0, Object var1, Object[] var2);

反射获取 Field 原理(getField()方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
@CallerSensitive
public Field getField(String name)
throws NoSuchFieldException, SecurityException {
// 检查调用getField()方法类的权限
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
// 真正获取属性的操作由getField0()方法完成
Field field = getField0(name);
if (field == null) {
throw new NoSuchFieldException(name);
}
return field;
}

private Field getField0(String name) throws NoSuchFieldException {
Field res;
// 查找所有声明的public属性
// Search declared public fields

// 从"root" fields找
if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) {
return res;
}
// 从接口找
// Direct superinterfaces, recursively
Class<?>[] interfaces = getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
Class<?> c = interfaces[i];
if ((res = c.getField0(name)) != null) {
return res;
}
}
// 从父类找
// Direct superclass, recursively
if (!isInterface()) {
Class<?> c = getSuperclass();
if (c != null) {
if ((res = c.getField0(name)) != null) {
return res;
}
}
}
return null;
}

// Returns an array of "root" fields. These Field objects must NOT
// be propagated to the outside world, but must instead be copied
// via ReflectionFactory.copyField.
private Field[] privateGetDeclaredFields(boolean publicOnly) {
checkInitted();
Field[] res;
ReflectionData<T> rd = reflectionData();
// 如果ReflectionData存在
if (rd != null) {
// 从ReflectionData中获取属性(ReflectionData在上面的“反射获取Method”中已经分析过了)
res = publicOnly ? rd.declaredPublicFields : rd.declaredFields;
if (res != null) return res;
}
// ReflectionData不存在,从JVM从获取
// No cached value available; request value from VM
res = Reflection.filterFields(this, getDeclaredFields0(publicOnly));
// 将获取到的Field[]赋给reflectionData,这样下次就有缓存了
if (rd != null) {
if (publicOnly) {
rd.declaredPublicFields = res;
} else {
rd.declaredFields = res;
}
}
return res;
}

// 创建好ReflectionData后就可以获取到Field[]
// 接着在Field[]中搜索符合条件的Field
private static Field searchFields(Field[] fields, String name) {
String internedName = name.intern();
// 遍历Field[]
for (int i = 0; i < fields.length; i++) {
// 如果Field名字一致
if (fields[i].getName() == internedName) {
// 复制一个Field返回
// 可以看出getField()方法和getDeclaredMethod()方法类似,每次返回的对象其实都是一个新的对象
return getReflectionFactory().copyField(fields[i]);
}
}
return null;
}

反射的使用

反射获取 Class

1
2
// 在使用Class.forName()方法时必须提供一个类的全名
Class aClass = Class.forName("com.test.reflectiontest.aClass");

反射创建对象

通过反射创建类对象主要有两种方式:

  • 通过 Class 的 newInstance() 方法。
  • 通过 Constructor 的 newInstance() 方法。
1
2
Class aClass = Class.forName("com.test.reflectiontest.aClass");
MyObject myObject = (MyObject) aClass.newInstance();
1
2
3
Class aClass = Class.forName("com.test.reflectiontest.aClass");
Constructor constructor = aClass.getConstructor();
MyObject myObject = (MyObject) constructor.newInstance();

通过 Constructor 对象创建类对象可以选择特定构造方法,而通过 Class 对象则只能使用默认的无参构造方法

1
2
3
4
// 调用有参数构造方法进行对象的初始化
Class aClass = Class.forName("com.test.reflectiontest.aClass");
Constructor constructor = aClass.getConstructor(String.class, int.class);
MyObject myObject = (MyObject) constructor.newInstance("test", 123);

反射获取方法

1
2
3
4
5
6
7
Method method = aClass.getMethod("someMethod",returnType.class);
// 获取方法参数类型
Class[] parameterTypes = method.getParameterTypes();
// 获取方法返回类型
Class returnType = method.getReturnType();
// 执行方法
method.invoke();
1
2
3
4
// 若方法为private类型,则
Method method =aClass.getDeclaredMethod("someMethod",returnType.class);
// 执行方法前需要取消权限检查
method.setAccessible(true);

反射获取属性

1
2
3
4
5
6
7
8
Field field = aClass.getField("someField");
// 获取属性名称
String fieldName = field.getName();
// 获取属性类型
Object fieldType = field.getType();
// Get/Set属性
Object value = field.get(aClass);
field.set(aClass, newValue);
1
2
3
4
// 若属性为private类型,需要用getDeclaredField()方法
Field field = aClass.getDeclaredField("someField");
// Get/Set前需要取消权限检查
field.setAccessible(true);

反射获取父类

1
Class superClass = aClass.getSuperclass();

反射获取修饰符

1
int modifiers = aClass.getModifiers();
1
2
3
4
5
6
7
8
9
10
11
12
13
// 检查修饰符类型
Modifier.isAbstract(int modifiers);
Modifier.isFinal(int modifiers);
Modifier.isInterface(int modifiers);
Modifier.isNative(int modifiers);
Modifier.isPrivate(int modifiers);
Modifier.isProtected(int modifiers);
Modifier.isPublic(int modifiers);
Modifier.isStatic(int modifiers);
Modifier.isStrict(int modifiers);
Modifier.isSynchronized(int modifiers);
Modifier.isTransient(int modifiers);
Modifier.isVolatile(int modifiers);

反射的应用场景

  • Idea 等 IDE 的自动补全功能,通过反射机制 IDE 可以自动把对象的方法和属性都显示出来。
  • JDBC 中通过 Class.forName() 动态加载 DB 的驱动。
  • Spring 中通过 XML 实现注入 Bean。
  • 序列化与反序列化中的自定义序列化会使用反射来检查对象是否实现了 writeObject()readObject() 两个方法。

反射性能慢的原因

  • 反射需要按名字来检索类和方法,有一定的时间开销。

  • 反射涉及类型的动态处理,某些虚拟机无法执行性能优化。

因此,同样功能的反射代码与非反射代码相比性能要慢,所以在性能敏感的应用中要避免使用反射。

  • 本文作者: Marticles
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!