<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
    似懂非懂  回復  更多評論
      
    主站蜘蛛池模板: 野花视频在线官网免费1| 中文字幕乱码免费看电影| 免费观看一级毛片| 一级美国片免费看| 久久亚洲精精品中文字幕| 色吊丝最新永久免费观看网站| 一个人看的www免费在线视频| 久久久久亚洲AV无码专区首JN| 国产大片线上免费看| 97青青草原国产免费观看| 亚洲AV第一成肉网| 亚洲av色福利天堂| 日本免费一区二区三区最新| 男女午夜24式免费视频| 亚洲国产欧洲综合997久久| 久热综合在线亚洲精品| 国产一区二区三区在线免费 | 国产v亚洲v天堂无码网站| 免费无码又黄又爽又刺激| 99久久精品毛片免费播放| 亚洲私人无码综合久久网| 久久综合九九亚洲一区| 亚洲成AⅤ人影院在线观看| 久久国内免费视频| 永久免费A∨片在线观看| 美女啪啪网站又黄又免费| 亚洲人成在线中文字幕| 亚洲VA中文字幕无码毛片| 亚洲国产激情一区二区三区| 久久久久久久免费视频| 久久午夜无码免费| 久久久久免费视频| 亚欧日韩毛片在线看免费网站| 亚洲高清毛片一区二区| 亚洲国产综合在线| 亚洲视频中文字幕| 久久精品国产亚洲综合色| 亚洲精品乱码久久久久久不卡| 在线观看免费污视频| 国产成人精品免费视频动漫| 久久午夜无码免费|