对于java的用户而言,反射技术对于咱们使用来讲是很是,下面仍是使用一个小的demo为例子 1.首先定一个类:java
public class Zhangsan implements Man { @Override public void findObject() { System.out.println("oh , i find you."); } } 复制代码
2.定一个测试类bash
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); } } 复制代码
下图就实现了对于对象的调用. markdown
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,ide
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.ui
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,设置膨胀次数.this
总结:
今天经过分析反射调用的源码,一块儿分析下反射调用过程,spa