对于java的用户而言,反射技术对于我们使用来说是非常,下面还是使用一个小的demo为例子 1.首先定一个类:
public class Zhangsan implements Man {
@Override
public void findObject() {
System.out.println("oh , i find you.");
}
}
2.定一个测试类
public class TestMain {
public static void main(String[] args) throws Throwable{
Method method = Class.forName("com.jdk14.demo.dynamic.myjdk.Man").getMethod("findObject");
Zhangsan zhangsan = new Zhangsan();
//1.Constructor
for(int i=0; i < 16; i++) {
method.invoke(zhangsan);
}
}
下图就实现了对于对象的调用.
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz,
Modifier.isStatic(modifiers) ? null : obj.getClass(),
modifiers);
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
Method类中有一个属性的root是顶部的Method,初始化是空, 然后就是从reflectionFactory#newMethodAccessor获取到 MethodAccessor,
private MethodAccessor acquireMethodAccessor() {
// First check to see if one has been created yet, and take it
// if so
MethodAccessor tmp = null;
if (root != null) tmp = root.getMethodAccessor();
if (tmp != null) {
methodAccessor = tmp;
} else {
// Otherwise fabricate one and propagate it up to the root
tmp = reflectionFactory.newMethodAccessor(this);
setMethodAccessor(tmp);
}
return tmp;
}
可以看出ReflectionFactory是里面单例对象,
public MethodAccessor newMethodAccessor(Method method) {
checkInitted();
if (Reflection.isCallerSensitive(method)) {
Method altMethod = findMethodForReflection(method);
if (altMethod != null) {
method = altMethod;
}
}
// use the root Method that will not cache caller class
Method root = langReflectAccess.getRoot(method);
if (root != null) {
method = root;
}
if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
return new MethodAccessorGenerator().
generateMethod(method.getDeclaringClass(),method.getName(),
method.getParameterTypes(),
method.getReturnType(),
method.getExceptionTypes(),
method.getModifiers());
} else {
NativeMethodAccessorImpl acc =
new NativeMethodAccessorImpl(method);
DelegatingMethodAccessorImpl res =
new DelegatingMethodAccessorImpl(acc);
acc.setParent(res);
return res;
}
}
然后看下NativeMethodAccessorImpl#invoke方法,这里是JNI调用方式,这里涉及一个概念,调用的膨胀阈值,是ReflectionFactory中inflationThreshold字段,默认是15,当反射调用大于15次,就是通过MethodAccessorGenerator#generateMethod底层是通过ClassFileAssembler这个类生成字节码,这样直接调用方法调用,效率要比Native要高,但是换来是生成class文件,这就是空间换取时间,通过设置parent#setdelegate方法,可以动态替换NativeMethodAccessorImpl为生成的MethodAccessorImpl.
public Object invoke(Object obj, Object[] args)
throws IllegalArgumentException, InvocationTargetException
{
// We can't inflate methods belonging to vm-anonymous classes because
// that kind of class can't be referred to by name, hence can't be
// found from the generated bytecode.
// numInvocations默认值是15
if (++numInvocations > ReflectionFactory.inflationThreshold()
&& !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
MethodAccessorImpl acc = (MethodAccessorImpl)
new MethodAccessorGenerator().
generateMethod(method.getDeclaringClass(), method.getName(),
method.getParameterTypes(),
method.getReturnType(),
method.getExceptionTypes(),
method.getModifiers());
parent.setDelegate(acc);
}
return invoke0(method, obj, args);
}
反射调用膨胀也可用通过 -Dsun.reflect.noInflation=true,直接打开开关. -Dsun.reflect.inflationThreshold=20,设置膨胀次数.
总结:
今天通过分析反射调用的源码,一起分析下反射调用过程,