不同classloader裝載的類不能互相訪問?


一,有兩個術語,一個叫“定義類加載器”,一個叫“初始類加載器”。
比如有如下的類加載器結構:
bootstrap
  ExtClassloader
    AppClassloader
    -自定義clsloadr1
    -自定義clsloadr2
如果用“自定義clsloadr1”加載java.lang.String類,那么根據雙親委派最終bootstrap會加載此類,那么bootstrap類就叫做該類的“定義類加載器”,而包括bootstrap的所有得到該類class實例的類加載器都叫做“初始類加載器”。

二,所說的“命名空間”,是指jvm為每個類加載器維護的一個“表”,這個表記錄了所有以此類加載器為“初始類加載器”(而不是定義類加載器,所以一個類可以存在於很多的命名空間中)加載的類的列表,所以,題目中的問題就可以解釋了:
CLTest是AppClassloader加載的,String是通過加載CLTest的類加載器也就是AppClassloader進行加載,但最終委派到bootstrap加載的(當然,String類其實早已經被加載過了,這里只是舉個例子)。所以,對於String類來說,bootstrap是“定義類加載器”,AppClassloader是“初始類加載器”。根據剛才所說,String類在AppClassloader的命名空間中(同時也在bootstrap,ExtClassloader的命名空間中,因為bootstrap,ExtClassloader也是String的初始類加載器),所以CLTest可以隨便訪問String類。這樣就可以解釋“處在不同命名空間的類,不能直接互相訪問”這句話了。

三,一個類,由不同的類加載器實例加載的話,會在方法區產生兩個不同的類,彼此不可見,並且在堆中生成不同Class實例。

四,那么由不同類加載器實例(比如-自定義clsloadr1,-自定義clsloadr2)所加載的classpath下和ext下的類,也就是由我們自定義的類加載器委派給AppClassloader和ExtClassloader加載的類,在內存中是同一個類嗎?
所有繼承ClassLoader並且沒有重寫getSystemClassLoader方法的類加載器,通過getSystemClassLoader方法得到的AppClassloader都是同一個AppClassloader實例,類似單例模式。
在ClassLoader類中getSystemClassLoader方法調用私有的initSystemClassLoader方法獲得AppClassloader實例,在initSystemClassLoader中:
sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
。。。
scl = l.getClassLoader();
AppClassloader是sun.misc.Launcher類的內部類,Launcher類在new自己的時候生成AppClassloader實例並且放在自己的私有變量loader里:
loader = AppClassLoader.getAppClassLoader(extclassloader);
值得一提的是sun.misc.Launcher類使用了一種類似單例模式的方法,即既提供了單例模式的接口getLauncher()又把構造函數設成了public的。但是在ClassLoader中是通過單件模式取得的Launcher 實例的,所以我們寫的每個類加載器得到的AppClassloader都是同一個AppClassloader類實例。
這樣的話得到一個結論,就是所有通過正常雙親委派模式的類加載器加載的classpath下的和ext下的所有類在方法區都是同一個類,堆中的Class實例也是同一個。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM