<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    DANCE WITH JAVA

    開發(fā)出高質量的系統(tǒng)

    常用鏈接

    統(tǒng)計

    積分與排名

    好友之家

    最新評論

    Java的類裝載器(Class Loader)和命名空間(NameSpace)

    摘要

    Java的類裝載器是Java動態(tài)性的核心,本文將向大家簡要介紹Java的類裝載器,及相關的parent delegation模型,命名空間,運行時包等概念,同時討論一些在學習中容易混淆的問題。

    類裝載器的功能及分類

    顧名思義,類裝載器是用來把類(class)裝載進JVM的。JVM規(guī)范定義了兩種類型的類裝載器:啟動內裝載器(bootstrap)和用戶自定義裝載器(user-defined class loader)。

    bootstrap是JVM自帶的類裝載器,用來裝載核心類庫,如java.lang.*等。由例1可以看出,java.lang.Object是由bootstrap裝載的。

    Java提供了抽象類ClassLoader,所有用戶自定義類裝載器都實例化自ClassLoader的子類。 System Class Loader是一個特殊的用戶自定義類裝載器,由JVM的實現(xiàn)者提供,在編程者不特別指定裝載器的情況下默認裝載用戶類。系統(tǒng)類裝載器可以通過ClassLoader.getSystemClassLoader() 方法得到。

    例1,測試你所使用的JVM的ClassLoader

    /*LoaderSample1.java*/
    public class LoaderSample1 {
    ??? public static void main(String[] args) {
    ??????? Class c;
    ??????? ClassLoader cl;
    ??????? cl = ClassLoader.getSystemClassLoader();
    ??????? System.out.println(cl);
    ??????? while (cl != null) {
    ??????????? cl = cl.getParent();
    ??????????? System.out.println(cl);
    ??????? }
    ??????? try {
    ??????????? c = Class.forName("java.lang.Object");
    ??????????? cl = c.getClassLoader();
    ??????????? System.out.println("java.lang.Object's loader is " + cl);
    ??????????? c = Class.forName("LoaderSample1");
    ??????????? cl = c.getClassLoader();
    ??????????? System.out.println("LoaderSample1's loader is " + cl);
    ??????? } catch (Exception e) {
    ??????????? e.printStackTrace();
    ??????? }
    ??? }
    }

    在我的機器上(Sun Java 1.4.2)的運行結果

    sun.misc.Launcher$AppClassLoader@1a0c10f
    sun.misc.Launcher$ExtClassLoader@e2eec8
    null 
    java.lang.Object's loader is null
    LoaderSample1's loader is sun.misc.Launcher$AppClassLoader@1a0c10f
    

    第一行表示,系統(tǒng)類裝載器實例化自類sun.misc.Launcher$AppClassLoader

    第二行表示,系統(tǒng)類裝載器的parent實例化自類sun.misc.Launcher$ExtClassLoader

    第三行表示,系統(tǒng)類裝載器parent的parent為bootstrap

    第四行表示,核心類java.lang.Object是由bootstrap裝載的

    第五行表示,用戶類LoaderSample1是由系統(tǒng)類裝載器裝載的

    parent delegation模型

    從1.2版本開始,Java引入了雙親委托模型,從而更好的保證Java平臺的安全。在此模型下,當一個裝載器被請求裝載某個類時,它首先委托自己的parent去裝載,若parent能裝載,則返回這個類所對應的Class對象,若parent不能裝載,則由parent的請求者去裝載。

    如圖1所示,loader2的parent為loader1,loader1的parent為system class loader。假設loader2被要求裝載類MyClass,在parent delegation模型下,loader2首先請求loader1代為裝載,loader1再請求系統(tǒng)類裝載器去裝載MyClass。若系統(tǒng)裝載器能成功裝載,則將MyClass所對應的Class對象的reference返回給loader1,loader1再將reference返回給loader2,從而成功將類MyClass裝載進虛擬機。若系統(tǒng)類裝載器不能裝載MyClass,loader1會嘗試裝載MyClass,若loader1也不能成功裝載,loader2會嘗試裝載。若所有的parent及l(fā)oader2本身都不能裝載,則裝載失敗。

    若有一個能成功裝載,實際裝載的類裝載器被稱為定義類裝載器,所有能成功返回Class對象的裝載器(包括定義類裝載器)被稱為初始類裝載器。如圖1所示,假設loader1實際裝載了MyClass,則loader1為MyClass的定義類裝載器,loader2和loader1為MyClass的初始類裝載器。

    ?

    需要指出的是,Class Loader是對象,它的父子關系和類的父子關系沒有任何關系。一對父子loader可能實例化自同一個Class,也可能不是,甚至父loader實例化自子類,子loader實例化自父類。假設MyClassLoader繼承自ParentClassLoader,我們可以有如下父子loader:

    ClassLoader loader1 = new MyClassLoader();
    //參數(shù) loader1 為 parent
    ClassLoader loader2 = new ParentClassLoader(loader1); 
    

    那么parent delegation模型為什么更安全了?因為在此模型下用戶自定義的類裝載器不可能裝載應該由父親裝載器裝載的可靠類,從而防止不可靠甚至惡意的代碼代替由父親裝載器裝載的可靠代碼。實際上,類裝載器的編寫者可以自由選擇不用把請求委托給parent,但正如上所說,會帶來安全的問題。

    命名空間及其作用

    每個類裝載器有自己的命名空間,命名空間由所有以此裝載器為創(chuàng)始類裝載器的類組成。不同命名空間的兩個類是不可見的,但只要得到類所對應的Class對象的reference,還是可以訪問另一命名空間的類。

    例2演示了一個命名空間的類如何使用另一命名空間的類。在例子中,LoaderSample2由系統(tǒng)類裝載器裝載,LoaderSample3由自定義的裝載器loader負責裝載,兩個類不在同一命名空間,但LoaderSample2得到了LoaderSample3所對應的Class對象的reference,所以它可以訪問LoaderSampl3中公共的成員(如age)。

    例2不同命名空間的類的訪問

    										/*LoaderSample2.java*/
    import java.net.*;
    import java.lang.reflect.*;
    public class LoaderSample2 {
    ??? public static void main(String[] args) {
    ??????? try {
    ??????????? String path = System.getProperty("user.dir");
    ??????????? URL[] us = {new URL("file://" + path + "/sub/")};
    ??????????? ClassLoader loader = new URLClassLoader(us);
    ??????????? Class c = loader.loadClass("LoaderSample3");
    ??????????? Object o = c.newInstance();
    ??????????? Field f = c.getField("age");
    ??????????? int age = f.getInt(o);
    ??????????? System.out.println("age is " + age);
    ??????? } catch (Exception e) {
    ??????????? e.printStackTrace();
    ??????? }
    ??? }
    										}
    								
    										/*sub/Loadersample3.java*/
    public class LoaderSample3 {
    ??? static {
    ??????? System.out.println("LoaderSample3 loaded");
    ??? }
    ??? public int age = 30;
    }

    編譯:javac LoaderSample2.java; javac sub/LoaderSample3.java

    運行:java LoaderSample2

    LoaderSample3 loaded
    age is 30
    

    從運行結果中可以看出,在類LoaderSample2中可以創(chuàng)建處于另一命名空間的類LoaderSample3中的對象并可以訪問其公共成員age。

    運行時包(runtime package)

    由同一類裝載器定義裝載的屬于相同包的類組成了運行時包,決定兩個類是不是屬于同一個運行時包,不僅要看它們的包名是否相同,還要看的定義類裝載器是否相同。只有屬于同一運行時包的類才能互相訪問包可見的類和成員。這樣的限制避免了用戶自己的代碼冒充核心類庫的類訪問核心類庫包可見成員的情況。假設用戶自己定義了一個類java.lang.Yes,并用用戶自定義的類裝載器裝載,由于java.lang.Yes和核心類庫java.lang.*由不同的裝載器裝載,它們屬于不同的運行時包,所以java.lang.Yes不能訪問核心類庫java.lang中類的包可見的成員。

    總結

    在簡單討論了類裝載器,parent delegation模型,命名空間,運行時包后,相信大家已經對它們的作用有了一定的了解。命名空間并沒有完全禁止屬于不同空間的類的互相訪問,雙親委托模型加強了Java的安全,運行時包增加了對包可見成員的保護。

    參考資料

    <<Inside The Java Virtual Machine>> by Bill Venners

    <<The Java Virtual Machine Specification>> by Sun Microsystems

    posted on 2006-12-08 11:30 dreamstone 閱讀(955) 評論(0)  編輯  收藏 所屬分類: jdk相關

    主站蜘蛛池模板: 国产三级在线观看免费| 人人狠狠综合久久亚洲高清| 亚洲一区二区三区久久久久| 99精品视频免费| 亚洲av成本人无码网站| 日韩亚洲人成网站| sss在线观看免费高清| 国产精品久久久久久亚洲小说| 亚洲六月丁香婷婷综合| 亚洲人成网男女大片在线播放| 久久九九亚洲精品| 亚洲精品高清无码视频| 久久久综合亚洲色一区二区三区| 国产亚洲精品拍拍拍拍拍| 亚洲成av人片不卡无码久久| 亚洲А∨精品天堂在线| 亚洲精品蜜桃久久久久久| 亚洲高清无码专区视频| 色影音免费色资源| 久久精品无码免费不卡| 亚洲人成网站在线在线观看| 亚洲国产综合无码一区| 四虎影视永久免费观看网址| 91青青国产在线观看免费| 免费人成大片在线观看播放| 亚洲国产精品网站久久| 国产亚洲人成网站观看| 四虎影永久在线高清免费| 免费观看美女用震蛋喷水的视频| 99久久99这里只有免费的精品| 亚洲日韩av无码中文| 中文字幕在线观看亚洲| 亚洲日韩精品无码一区二区三区 | 花蝴蝶免费视频在线观看高清版 | 黄网站色在线视频免费观看| 一级一黄在线观看视频免费| 亚洲国产日韩a在线播放| 亚洲国产成人手机在线电影bd | 久久99国产综合精品免费| 免费无码午夜福利片 | 亚洲第一极品精品无码久久|