真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java方法反射實現(xiàn)原理詳解

博主說:Java 反射機制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調(diào)用它的任意方法和屬性;這種動態(tài)獲取信息以及動態(tài)調(diào)用對象方法的功能稱為 Java 語言的反射機制。在本文中,占小狼分析了 Java 反射機制的實現(xiàn)原理(源碼),感興趣的同學(xué)可以通過閱讀本文花上幾分鐘了解了解。

站在用戶的角度思考問題,與客戶深入溝通,找到松江網(wǎng)站設(shè)計與松江網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網(wǎng)站設(shè)計、成都網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、空間域名、網(wǎng)絡(luò)空間、企業(yè)郵箱。業(yè)務(wù)覆蓋松江地區(qū)。

正文

Java方法反射實現(xiàn)原理詳解

方法反射實例

public class ReflectCase {

  public static void main(String[] args) throws Exception {
    Proxy target = new Proxy();
    Method method = Proxy.class.getDeclaredMethod("run");
    method.invoke(target);
  }

  static class Proxy {
    public void run() {
      System.out.println("run");
    }
  }
}

通過 Java 的反射機制,可以在運行期間調(diào)用對象的任何方法,如果大量使用這種方式進行調(diào)用,會有性能或內(nèi)存隱患么?為了徹底了解方法的反射機制,只能從底層代碼入手啦!

Method 獲取

調(diào)用 Class 類的getDeclaredMethod可以獲取指定方法名和參數(shù)的方法對象 Method。

getDeclaredMethod

Java方法反射實現(xiàn)原理詳解

其中privateGetDeclaredMethods方法從緩存或 JVM 中獲取該 Class 中申明的方法列表,searchMethods方法將從返回的方法列表里找到一個匹配名稱和參數(shù)的方法對象。

searchMethods

Java方法反射實現(xiàn)原理詳解

如果找到一個匹配的 Method,則重新復(fù)制一份返回,即Method.copy()方法。

Java方法反射實現(xiàn)原理詳解

所次每次調(diào)用getDeclaredMethod方法返回的 Method 對象其實都是一個新的對象,且新對象的root屬性都指向原來的 Method 對象,如果需要頻繁調(diào)用,最好把 Method 對象緩存起來。

privateGetDeclaredMethods

從緩存或 JVM 中獲取該 Class 中申明的方法列表,實現(xiàn)如下:

Java方法反射實現(xiàn)原理詳解

其中reflectionData()方法實現(xiàn)如下:

Java方法反射實現(xiàn)原理詳解

這里有個比較重要的數(shù)據(jù)結(jié)構(gòu)ReflectionData,用來緩存從 JVM 中讀取類的如下屬性數(shù)據(jù):

Java方法反射實現(xiàn)原理詳解

從reflectionData()方法實現(xiàn)可以看出:reflectionData對象是SoftReference類型的,說明在內(nèi)存緊張時可能會被回收,不過也可以通過-XX:SoftRefLRUPolicyMSPerMB參數(shù)控制回收的時機,只要發(fā)生GC就會將其回收,如果reflectionData被回收之后,又執(zhí)行了反射方法,那只能通過newReflectionData方法重新創(chuàng)建一個這樣的對象了,newReflectionData方法實現(xiàn)如下:

Java方法反射實現(xiàn)原理詳解

通過unsafe.compareAndSwapObject方法重新設(shè)置reflectionData字段;在privateGetDeclaredMethods方法中,如果通過reflectionData()獲得的ReflectionData對象不為空,則嘗試從ReflectionData對象中獲取declaredMethods屬性,如果是第一次,或則被GC回收之后,重新初始化后的類屬性為空,則需要重新到 JVM 中獲取一次,并賦值給ReflectionData,下次調(diào)用就可以使用緩存數(shù)據(jù)了。

Method 調(diào)用

獲取到指定的方法對象 Method 之后,就可以調(diào)用它的invoke方法了,invoke實現(xiàn)如下:

Java方法反射實現(xiàn)原理詳解

應(yīng)該注意到:這里的MethodAccessor對象是invoke方法實現(xiàn)的關(guān)鍵,一開始methodAccessor為空,需要調(diào)用acquireMethodAccessor生成一個新的MethodAccessor對象,MethodAccessor本身就是一個接口,實現(xiàn)如下:

Java方法反射實現(xiàn)原理詳解

在acquireMethodAccessor方法中,會通過ReflectionFactory類的newMethodAccessor創(chuàng)建一個實現(xiàn)了MethodAccessor接口的對象,實現(xiàn)如下:

Java方法反射實現(xiàn)原理詳解

在ReflectionFactory類中,有 2 個重要的字段:noInflation(默認false)和inflationThreshold(默認15),在checkInitted方法中可以通過-Dsun.reflect.inflationThreshold=xxx和-Dsun.reflect.noInflation=true對這兩個字段重新設(shè)置,而且只會設(shè)置一次;如果noInflation為false,方法newMethodAccessor都會返回DelegatingMethodAccessorImpl對象,DelegatingMethodAccessorImpl的類實現(xiàn):

Java方法反射實現(xiàn)原理詳解

其實,DelegatingMethodAccessorImpl對象就是一個代理對象,負責(zé)調(diào)用被代理對象delegate的invoke方法,其中delegate參數(shù)目前是NativeMethodAccessorImpl對象,所以最終 Method 的invoke方法調(diào)用的是NativeMethodAccessorImpl對象invoke方法,實現(xiàn)如下:

Java方法反射實現(xiàn)原理詳解

這里用到了ReflectionFactory類中的inflationThreshold,當(dāng)delegate調(diào)用了15次invoke方法之后,如果繼續(xù)調(diào)用就通過MethodAccessorGenerator類的generateMethod方法生成MethodAccessorImpl對象,并設(shè)置為delegate對象,這樣下次執(zhí)行Method.invoke時,就調(diào)用新建的MethodAccessor對象的invoke()方法了。這里需要注意的是:generateMethod方法在生成MethodAccessorImpl對象時,會在內(nèi)存中生成對應(yīng)的字節(jié)碼,并調(diào)用ClassDefiner.defineClass創(chuàng)建對應(yīng)的 Class 對象,實現(xiàn)如下:

Java方法反射實現(xiàn)原理詳解

在ClassDefiner.defineClass方法實現(xiàn)中,每被調(diào)用一次都會生成一個DelegatingClassLoader類加載器對象:

Java方法反射實現(xiàn)原理詳解

這里每次都生成新的類加載器,是為了性能考慮,在某些情況下可以卸載這些生成的類,因為類的卸載是只有在類加載器可以被回收的情況下才會被回收的,如果用了原來的類加載器,那可能導(dǎo)致這些新創(chuàng)建的類一直無法被卸載,從其設(shè)計來看本身就不希望這些類一直存在內(nèi)存里的,在需要的時候有就行啦!

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。


網(wǎng)站標(biāo)題:Java方法反射實現(xiàn)原理詳解
URL分享:http://weahome.cn/article/pdccij.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部