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

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

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

    Jhonney的專欄

       ----人見人愛
    隨筆 - 49, 文章 - 1, 評論 - 23, 引用 - 0
    數據加載中……

    走出ClassLoader迷宮

    quto:http://www.tkk7.com/lihuaxajh/articles/94371.html
    other resources:
        1.http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html?page=1
        2.http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html?page=2  
        3.http://www.javaworld.com/javaworld/javaqa/2003-03/01-qa-0314-forname.html
        4.http://www.theserverside.com/news/thread.tss?thread_id=40763
        5.http://www.matrix.org.cn/resource/article/43/43875_Class_Loading.html
        6.http://blog.sina.com.cn/s/blog_4b6047bc0100096v.html
        7.http://blog.sina.com.cn/s/blog_4b6047bc0100097p.html
    這個問題經常出現在編寫框架代碼
    , 需要動態加載很多類和資源的時候 . 通常當你需要動態加載資源的時候 , 你至少有三個 ClassLoader 可以選擇 :

    1.   系統類加載器或叫作應用類加載器 (system classloader or application classloader)
    2.  當前類加載器
    3.  當前線程類加載器

    上面的問題指的是最后一種類加載器 . 哪種類加載器是正確的選擇呢 ?

    第一種選擇可以很容易地排除 : 系統類加載器 (system classloader). 這個類加載器處理 -classpath 下的類加載工作 , 可以通過 ClassLoader.getSystemClassLoader() 方法調用 . ClassLoader 下所有的 getSystemXXX() 的靜態方法都是通過這個方法定義的 . 在你的代碼中 , 你應該盡量少地調用這個方法 , 以其它的類加載器作為代理 . 否則你的代碼將只能工作在簡單的命令行應用中 , 這個時候系統類加載器 (system classloader) JVM 最后創建的類加載器 . 一但你把代碼移到 EJB, Web 應用或 Java Web Start 應用中 , 一定會出問題 .

          所以我們來看第二種選擇 : 當前上下文環境下的類加載器 . 根據定義 , 當前類加載器就是你當前方法所屬的類的加載器 . 在運行時類之間動態聯編 , 及調用 Class.forName,() Class.getResource() 等類似方法時 , 這個類加載器會被隱含地使用 . It is also used by syntactic constructs like X.class class literals.

        線程上下文類型加載器是在Java 2平臺上被引入的. 每一個線程都有一個類加載器與之對應(除非這個線程是被本地代碼創建的). 這個類加載器是通過Thread.setContextClassLoaser()方法設置的. 如果你不在線程構造后調用這個方法, 這個線程將從它的父線程中繼承相應的上下文類加載器. 如果在整個應用中你不做任何特殊設置, 所有的線程將都以系統類加載器(system classloader)作為自己的線程上下文類加載器. 自從WebJ2EE應用服務器使用成熟的類加載器機制來實現諸如JNDI, 線程池, 組件熱部署等功能以來, 這種在整個應用中不做任何線程類加載器設置的情況就很少了.

        為什么線程上下文類加載器存在于如此重要的位置呢? 這個概念在J2SE中的引入并不引人注目. 很多開發人員對這一概念迷惑的原因是Sun公司在這方面缺乏適當的指引和文檔.

        事實上, 上下文類加載器提供了類加載機制的后門, 這一點也在J2SE中被引入了. 通常, JVM中的所有類加載器被組織成了有繼承層次的結構, 每一個類加載器(除了引導JVM的原始類加載器)都有一個父加載器. 每當被請示加載類時, 類加載器都會首先請求其父類加載器, 只有當父類加載器不能加載時, 才會自己進行類加載.

       有時候這種類加載的順序安排不能正常工作, (此 處的意思是:正常情況下都是從子類加載器到根類加載器請求,萬一有根類里需要加載子類時,這種順序就不能滿足要求,就要有一條反向的通道,即得到子類加載 器,這樣就用到了thread context classloader,因為通過thread.getcontextclassloader()可以得到子類加載器).通常當必須動態加載應用程序開發人員提供的資源的時候. JNDI為例: 它的內容(J2SE1.3開始)就在rt.jar中的引導類中實現了, 但是這些JNDI核心類需要動態加載由獨立廠商實現并部署在應用程序的classpath下的JNDI提供者. 這種情況就要求一個父classloader(本例, 就是引導類加載器)去加載對于它其中一個子classloader(本例, 系統類加載器)可見的類. 這時通常的類加載代理機制不能實現這個要求. 解決的辦法(workaround)就是, JNDI核心類使用當前線程上下文的類加載器, 這樣, 就基本的類加載代理機制的相反方向建立了一條有效的途徑.

        另外, 上面一段可能讓你想起一些其它的事情: XML解析Java API(JAXP). 是的, JAXP只是J2SE的擴展進, 它很自然地用當前類加載器來引導解析器的實現. 而當JAXP被加入到J2SE1.4的核心類庫中時, 它的類加載也就改成了用當前線程類加載器, JNDI的情況完全類似(也使很多程序員很迷惑). 明白為什么我說來自Sun的指導很缺乏了吧?

       在以上的介紹之后, 我們來看關鍵問題: 這兩種選擇(當前類加載器和當前線程類加載器)都不是在所有環境下都適用. 有些人認為當前線程類加載器應該成為新的標準策略. 但是, 如果這樣, 當多個線程通過共享數據進行交互的時, 將會呈現出一幅極其復雜的類加載的畫面, 除非它們全部使用了同一個上下文的類加載器. 進一步說, 在某些遺留下來的解決方案中, 委派到當前類加載器的方法已經是標準. 比如對Class.forName(String)的直接調用(這也是我為什么推薦盡量避免對這個方法進行調用的原因). 即使你努力去只調用上下文相關的類加載器, 仍然會有一些代碼會不由你控制. 這種不受控制的類加載委派機制是混入是很危險的.

        更嚴重的問題, 某些應用服務器把環境上下文及當前類加載器設置到不同的類加載器實例上, 而這些類加載器有相同的類路徑但卻沒有委派機制中的父子關系. 想想這為什么十分可怕. 要知道類加載器定義并加載的類實例會帶有一個JVM內部的ID. 如果當前類加載器加載一個類X的實例, 這個實例調用JNDI查找類Y的實例, 些時的上下文的類加載器也可以定義了加載類Y實例. 這個類Y的定義就與當前類加載器看到的類Y的定義不同. 如果進行強制類型轉換, 則產生異常.

       這種混亂的情況還將在Java中存在一段時間. 對于那些需要動態加載資源的J2SEAPI, 我們來猜想它們的類加策略. 例如:

    Ø         JNDI 使用線程上下文類加載器

    Ø         Class.getResource() Class.forName()使用當前類加載器

    Ø         JAXP(J2SE 1.4 及之后)使用線程上下文類加載器

    Ø         java.util.ResourceBundle 使用調用者的當前類加載器

    Ø         URL protocol handlers specified via java.protocol.handler.pkgs system property are looked up in the bootstrap and system classloaders only

    Ø         Java 序列化API默認使用調用者當前的類加載器

    這些類及資源的加載策略問題, 肯定是J2SE領域中文檔最及說明最缺乏的部分了.

    posted on 2008-03-23 02:57 Jhonney 閱讀(454) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲成年看片在线观看| 色屁屁在线观看视频免费| 中文字幕亚洲专区| 免费毛片在线视频| 亚洲宅男天堂在线观看无病毒| 最近最好最新2019中文字幕免费| 国产亚洲午夜精品| 亚洲va成无码人在线观看| 亚洲国产精品特色大片观看完整版| 免费日本黄色网址| 好男人视频社区精品免费| 少妇无码一区二区三区免费| 一级女性全黄生活片免费看| 精品韩国亚洲av无码不卡区| 亚洲性色精品一区二区在线| 亚洲无线一二三四区| 久久精品国产亚洲| 亚洲中文字幕久久精品无码APP| 日本一道一区二区免费看| 成年人免费网站在线观看| 16女性下面扒开无遮挡免费| 国产成人精品免费久久久久| fc2免费人成为视频| 特级毛片aaaa免费观看| 免费一级全黄少妇性色生活片| 亚洲AV无码之国产精品| 亚洲乱妇老熟女爽到高潮的片| 亚洲www在线观看| 亚洲一区电影在线观看| 亚洲精品日韩专区silk| 亚洲网站视频在线观看| 亚洲成AV人片久久| 亚洲av专区无码观看精品天堂| 亚洲一级毛片在线观| 亚洲乱码在线卡一卡二卡新区| 亚洲综合无码一区二区痴汉| 亚洲一区二区三区成人网站 | 亚洲成_人网站图片| 亚洲乱码卡三乱码新区| 亚洲国产中文在线视频| 国产成人亚洲精品|