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

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

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

    隨筆-72  評論-20  文章-0  trackbacks-1
    1         問題背景
    我們都知道,Java平臺一大亮點就在于其類裝載器體系結構,這使得JVM可以在運行期從Java API,擴展路經(java.ext.path),classpath以及用戶指定的位置(文件或網絡)中載入所需的class,從而達到動態裝載的目的。然而其類裝載器委托模型在保證了安全性和強大功能的同時,也導致了相當的復雜性,有很多地方一旦我們不加注意的話就將導致錯誤。這里我希望通過一些小例子來展示動態裝載的某些方面,深入地了解一下怎么進行動態裝載,會遇到什么樣的問題,并就問題的原因與解決方法進行討論。
    也許有人會說:我的程序不用什么動態裝載,平時運行程序就是java –classpath … myPkg.my不就行了嗎?不過我總是聽前輩說,要想完全了解一個系統下的程序設計,就必須要深入研究這個平臺的特性,做到心中有數,做起程序才不會處處制肘。類的動態裝載是Java平臺最顯著的特征之一,許多著名的項目—Tomcat,Eclipse都使用自定義類裝載器來裝載運行時所需的類,如果連什么是動態裝載和怎么動態裝載都沒弄明白,還能去玩自定義類裝載器嗎?所以還是不要浮躁,讓我們從基礎開始做起吧。
    不過,我要說明的是你在看我這篇文章之前最好先熟悉一下Java的類裝載器體系結構以及其委托模型,我在這里將不加贅述,推薦先看《Java深度歷險》或《深入Java虛擬機》的第八章。
    2         問題研究
    我要討論的問題是:讓一個在my/目錄下名為my.Main的類在運行期讀取util/中的util.Tool類。
    l      實驗一
    我的實驗目錄結構如下
    其中my.Main的代碼如下:
    util.Tool的代碼如下:
    在my.Main的代碼中16行可以看到,我定義了一個URLClassLoader,想要讀取在同一根目錄下的/util/Tool.class,接下來我們運行如下命令,來查看運行結果:
    如上可見,util.Tool被順利裝載了,可是裝載它的卻是AppClassLoader,而不是我們想要的URLClassLoader!這是為什么呢?
    原因很簡單,因為我們將util/Tool.class放到了JVM系統變量”user.dir”所指定的目錄下,而該JVM系統變量的默認值為程序所在的根目錄,相當于把classpath 設置成了”.”,也就是相當于執行了命令:
    java –classpath . my.Main
    于是,正因為util.Tool在classpath下,于是JVM就在在載入my.Main的同時也用AppClassLoader將util.Tool載入到JVM了。我們可以通過如下命令看得更清楚一些:
    java –verbose my.Main
    看到了嗎?由于AppClassLoader預先載入了util.Tool類,而且在URLClassLoader的loadClass()方法中有如下語句:Class cls = getLoadedClass(String className);如果cls!=null的話,loadClass()就會返回已經載入過的(即由AppClassLoader所載入的)util.Tool類,所以我們才會看到以上結果。
    l      實驗二
    為了解決以上問題,我決定按如下方式組織我的目錄結構
    然后對Main.class進行一些修改:
    嗯,這下我們不會為util.Tool被提前載入而煩惱了,因為載入my.Main的AppClassLoader找不到換了位置的util.Tool類了。這回可能有人會問:subdir不是還在”user.dir”所指向的目錄下嗎?怎么只是多建了一層目錄它就找不到了呢?原因是AppClassLoader是URLClassLoader的子類,它在載入class的時候也是根據該類的URL來進行定位的。那我們的例子來說,在“實驗一”的最后一個圖中我們可以看到,util.Tool被載入的位置為:file1:c:/Test1,JVM得到這個URL之后,將util.Tool中的”.”變為”/”,在所得字符串結尾處加上”.class”,最后將該字符串加到file1:c:/Test1后面,就得到了最終util.Tool的URL:file1:c:/Test1/util/Tool.class。而當加了一層subdir目錄之后,AppClassLoader就找不到file1:c:/Test1/util/Tool.class了,而只能由程序中定義的URLClassLoader來載入。
     這時我們運行程序,所得結果如下:
    可以看到,util.Tool確實已經我定義的URLClassLoader被載入并初始化了,可是為什么最后卻有一個奇怪的異常呢?NoClassDefFoundError?util.Tool類不是都載入了嗎?怎么還找不到它的定義呢?
    這個問題需要從JVM的裝載機制說起。對于每個JVM實例,除了內置的三個內置的類裝載器(BootStrapClassLoader,ExtClassLoader,AppClassLoader)之外,還可能有一些用戶自定義的類裝載器,而這些類裝載器可能在一個程序運行周期內載入同一個類,即AppClassLoader和我自定義的類裝載器MyClassLoader可能同時需要載入util.Tool類。為了避免沖突,JVM為每個類裝載器都建立一個命名空間,并以此作為其訪問邊界。例如,如果my.Main想要引用util.Tool類,則它們必須是由同一裝載器載入的,也就是說,由于my.Main是由AppClassLoader載入的,那么util.Tool也必須由AppClassLoader載入才行,否則就會出現上述錯誤。
    問題解決的方法很簡單,只需要讓my.Main和util.Tool由同一類裝載器載入就行了。
    l      實驗三
    為了讓my.Main和util.Tool由同一類裝載器載入,我定義了一個啟動類—boot.BootStrap類:
    在這里,我用自己的類裝載器ucl來裝載my.Main類,并用reflection API來調用其main()方法,同時也對my.Main稍作修改
    然后執行一下看看結果:
    圖中可以很清楚的看到BootStrap類則是由AppClassLoader載入的,而Main類和Tool類都是由同一個URLClassLoader在運行期動態載入的。至此,我們完成了對類的動態載入的全部說明和實驗,希望對你能有所幫助。 
    posted on 2007-07-27 22:28 前方的路 閱讀(359) 評論(1)  編輯  收藏 所屬分類: Java技術

    評論:
    # re: 動態裝載問題的研究 2012-03-29 11:21 | yangzg
    似懂非懂  回復  更多評論
      
    主站蜘蛛池模板: 国产免费网站看v片在线| 色九月亚洲综合网| 免费人妻无码不卡中文字幕系| 国产成人亚洲精品影院| 一级黄色片免费观看| 亚洲精品乱码久久久久久不卡| 日韩精品无码免费视频| 亚洲中文字幕成人在线| 国产精品偷伦视频免费观看了| 中文字幕亚洲一区| 中国精品一级毛片免费播放| 国产精品亚洲а∨无码播放| 无码精品一区二区三区免费视频 | 中文字幕高清免费不卡视频| 国产成人精品日本亚洲专区61 | 国产成人免费网站在线观看| 国产成人亚洲精品蜜芽影院| MM131亚洲国产美女久久| 视频免费在线观看| 亚洲国产精品久久丫| 日韩成人免费视频播放| 一级一级毛片免费播放| 亚洲国产成人久久精品影视| 99久久久国产精品免费无卡顿| 亚洲国产欧美一区二区三区| 亚洲av无码天堂一区二区三区 | 99久久免费国产精品热| 337p日本欧洲亚洲大胆艺术| 成人毛片免费网站| 美女无遮挡拍拍拍免费视频| 日韩精品一区二区亚洲AV观看| 成全影视免费观看大全二| jizz在线免费观看| 亚洲国产日韩在线成人蜜芽 | 亚洲一区二区三区在线| 免费一级毛片在线播放不收费| 日韩精品无码免费专区午夜| 亚洲人妖女同在线播放| 亚洲精品老司机在线观看| 波多野结衣免费在线观看| 美女无遮挡免费视频网站|