1. 程式人生 > >Java反射機制及原理

Java反射機制及原理

一、概念 java程式執行時動態的建立類並呼叫類的方法和屬性   二、原理簡介
Class<?> clz = Class.forName("java.util.ArrayList");
ArrayList object = (ArrayList) clz.newInstance();
Method method = clz.getMethod("add",Object.class);
method.invoke(list , "sss");
  上面就是我們最常見的反射的例子,前兩行實現了類的裝載、連結(驗證、準備、解析)、初始化(newInstance其實也是通過反射呼叫類的<init>方法),後面兩行實現了從class物件中獲取物件然後執行反射呼叫。   設想,假如我們要實現Invoke方法,是不是隻要實現如下類即可:
public class Method {
 
    public void invoke(Object obj , Object... args) {
        ArrayList list = (ArrayList)obj;
        list.add(args);
    }
}
  反射的原理之一:就是動態的生成類似於上述的位元組碼,載入到JVM中執行   獲取Method物件流程   上面的Class物件是在載入類時由JVM構造的,JVM為每個類管理一個獨一無二的CLASS物件,這份CLASS物件裡維護著該類的所有 Method,Field,Constructor的cache,這份cache也可以稱作為根物件。每次getMethod獲取到的Method物件都持有對根物件的引用,因為一些重量級的Method的成員變數(主要是MethodAccessor),我們不希望每次建立Method物件都要重新初始化,於是所有代表同一個方法的Method物件都共享著根物件的MethodAccessor,每一次建立都會呼叫根物件的copy方法複製一份:
Method copy() { 
        Method res = new Method(clazz, name, parameterTypes, returnType,
                                exceptionTypes, modifiers, slot, signature,
                                annotations, parameterAnnotations, annotationDefault);
        res.root = this;
        res.methodAccessor = methodAccessor;
        return res;
    }
  呼叫invoke方法流程 method.invoke方法會首先獲取一個MethodAccessor,首先會從Method的根物件中獲取MethodAccessor,如果為空,用reflectionFactory.newMethodAccessor返回DelegatingMethodAccessorImpl例項,然後將MethodAccessor賦值給Method的root物件中(因為MethodAccessor是所有Method共用的),然後呼叫DelegatingMethodAccessorImpl中的invoke方法,當呼叫invoke的次數大於15次以後,MethodAccessor將由java程式碼生成   整體流程圖: