Java反射機制在程序運行時,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性。這種動態的獲取信息以及動態調用對象的方法 的功能稱爲java的反射機制。java
首先你須要瞭解類加載的過程,這裏咱們簡單提一下(加載-驗證-準備-解析-初始化),反射是靠JVM和Class相關類實現的。api
按照這個例子,咱們調試下看看具體實現。併發
@Data public class Person { private String name; public static void main(String[] args) throws Exception { Person person = new Person(); person.setName("lewis"); for (int i = 0; i < 16; i++) { Method method = Person.class.getMethod("getName"); System.out.println(method.invoke(person)); } } }
@CallerSensitive public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { // 檢查方法是否爲public if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { Class<?> caller = Reflection.getCallerClass(); // 權限校驗 checkAccess(caller, clazz, obj, modifiers); } } // MethodAccessor實現有兩個版本,一個是Java實現的,另外一個是JNI實現的 MethodAccessor ma = methodAccessor; // read volatile if (ma == null) { ma = acquireMethodAccessor(); } return ma.invoke(obj, args); }
咱們上面提到了 MethodAccessor 有兩個實現,Java版本和JNI版本(就是java native),ide
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); DelegatingMethodAccessorImpl var3 = new DelegatingMethodAccessorImpl(var2); var2.setParent(var3); return var3; } }
class DelegatingMethodAccessorImpl extends MethodAccessorImpl { private MethodAccessorImpl delegate; DelegatingMethodAccessorImpl(MethodAccessorImpl var1) { this.setDelegate(var1); } public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException { return this.delegate.invoke(var1, var2); } void setDelegate(MethodAccessorImpl var1) { this.delegate = var1; } }
來看看NativeMethodAccessorImpl實現,超過15次之後調用反射,就會經過咱們上面提到的中間層 DelegatingMethodAccessorImpl 所引用的 MethodAccessor 都是java 版。高併發
class NativeMethodAccessorImpl extends MethodAccessorImpl { private final Method method; private DelegatingMethodAccessorImpl parent; private int numInvocations; NativeMethodAccessorImpl(Method var1) { this.method = var1; } public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException { // 方法被調用時,程序調用計數器都會增長1,看看是否超過閾值 if (++this.numInvocations > ReflectionFactory.inflationThreshold() && !ReflectUtil.isVMAnonymousClass(this.method.getDeclaringClass())) { // 超過15次 則調用MethodAccessorGenerator.generateMethod()來生成Java版的MethodAccessor的實現類 // 而且改變經過中間層,後續DelegatingMethodAccessorImpl所引用的MethodAccessor改成Java版 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); } // native版本,JNI方式調用 return invoke0(this.method, var1, var2); } void setParent(DelegatingMethodAccessorImpl var1) { this.parent = var1; } private static native Object invoke0(Method var0, Object var1, Object[] var2); }
在默認狀況下,方法的反射調用爲委派實現,委派給本地實現來進行方法調用。在調用超過 15 次以後,委派實現便會將委派對象切換至動態實現。這個動態的字節碼是在Java運行過程當中經過ASM自動生成的,它將直接使用 invoke 指令來調用目標方法。工具
繼續查看代碼,能夠看到sun.reflect.MethodAccessorGenerator#generate
的實現是調用asm字節碼加強工具來生成類,此過程較長,不在此列出。在該方法的最後,咱們發現有這樣一個操做sun.reflect.ClassDefiner#defineClass
,查看其源碼post
static Class<?> defineClass(String name, byte[] bytes, int off, int len, final ClassLoader parentClassLoader) { // 建立一個DelegatingClassLoader用來加載生成的類 ClassLoader newLoader = AccessController.doPrivileged( new PrivilegedAction<ClassLoader>() { public ClassLoader run() { return new DelegatingClassLoader(parentClassLoader); } }); return unsafe.defineClass(name, bytes, off, len, newLoader, null); }