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

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

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

    迷途書童

    敏感、勤學(xué)、多思
    隨筆 - 77, 文章 - 4, 評(píng)論 - 86, 引用 - 0
    數(shù)據(jù)加載中……

    ClassLoader分析

    1 ????????? 前言

    ClassLoader Java 虛擬機(jī) (JVM) 的類裝載子系統(tǒng),它負(fù)責(zé)將 Java 字節(jié)碼裝載到 JVM 中, 并使其成為 JVM 一部分。 JVM 的類動(dòng)態(tài)裝載技術(shù)能夠在運(yùn)行時(shí)刻動(dòng)態(tài)地加載或者替換系統(tǒng)的某些功能模塊 , 而不影響系統(tǒng)其他功能模塊的正常運(yùn)行。本文將分析 JVM 中的類裝載系統(tǒng),探討 JVM 中類裝載的原理、實(shí)現(xiàn)以及應(yīng)用。

    2 ????????? 裝載過程簡(jiǎn)介

    類裝載就是尋找一個(gè)類或是一個(gè)接口的字節(jié)碼文件并通過解析該字節(jié)碼來構(gòu)造代表這個(gè)類或是這個(gè)接口的 class 對(duì)象的過程。在 Java 中,類裝載器把一個(gè)類裝入 Java 虛擬機(jī)中,要經(jīng)過三個(gè)步驟來完成:裝載、鏈接和初始化,其中鏈接又可以分成校驗(yàn)、準(zhǔn)備和解析三步,除了解析外,其它步驟是嚴(yán)格按照順序完成的,各個(gè)步驟的主要工作如下:

    1.??????? 裝載:查找和導(dǎo)入類或接口的字節(jié)碼;

    2.??????? 鏈接:執(zhí)行下面的校驗(yàn)、準(zhǔn)備和解析步驟,其中解析步驟是可以選擇的;

    l??????? 校驗(yàn):檢查導(dǎo)入類或接口的二進(jìn)制數(shù)據(jù)的正確性;

    l??????? 準(zhǔn)備:給類的靜態(tài)變量分配并初始化存儲(chǔ)空間;

    l??????? 解析:將符號(hào)引用轉(zhuǎn)成直接引用;

    3.??????? 初始化:激活類的靜態(tài)變量的初始化 Java 代碼和靜態(tài) Java 代碼塊。

    至于在類裝載和虛擬機(jī)啟動(dòng)的過程中的具體細(xì)節(jié)和可能會(huì)拋出的錯(cuò)誤,請(qǐng)參看《 Java 虛擬機(jī)規(guī)范》以及《深入 Java 虛擬機(jī)》。 由于本文的討論重點(diǎn)不在此就不再多敘述。

    2.1 ????????? 裝載的實(shí)現(xiàn)

    JVM 中類的裝載是由 ClassLoader 和它的子類來實(shí)現(xiàn)的。 Java ClassLoader 是一個(gè)重要的 Java 運(yùn)行時(shí)系統(tǒng)組件,它負(fù)責(zé)在運(yùn)行時(shí)查找和裝入 Java 字節(jié)碼。

    Java 中, ClassLoader 是一個(gè)抽象類,它在包 java.lang 中。可以這樣說,只要了解了 ClassLoader 中的一些重要的方法,再結(jié)合上面所介紹的 JVM 中類裝載的具體的過程,對(duì)動(dòng)態(tài)裝載類這項(xiàng)技術(shù)就有了一個(gè)比較大概的掌握,這些重要的方法包括以下幾個(gè):

    1.??????? loadCass 方法: loadClass(String name ,boolean resolve) 其中 name 參數(shù)指定了 JVM 需要的類的名稱 , 該名稱以類的全限定名表示,如 Java.lang.Object resolve 參數(shù)告訴方法是否需要解析類,在初始化類之前,應(yīng)考慮類解析,并不是所有的類都需要解析,如果 JVM 只需要知道該類是否存在或找出該類的超類,那么就不需要解析。這個(gè)方法是 ClassLoader 的入口點(diǎn)。

    2.??????? defineClass 方法 ? 這個(gè)方法接受類文件的字節(jié)數(shù)組并把它轉(zhuǎn)換成 Class 對(duì)象。字節(jié)數(shù)組可以是從本地文件系統(tǒng)或網(wǎng)絡(luò)裝入的數(shù)據(jù)。它把字節(jié)碼分析成運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)、校驗(yàn)有效性等等。

    3.??????? findSystemClass 方法 ? findSystemClass 方法從本地文件系統(tǒng)裝入 Java 字節(jié)碼。它在本地文件系統(tǒng)中尋找類文件,如果存在,就使用 defineClass 將字節(jié)數(shù)組轉(zhuǎn)換成 Class 對(duì)象。當(dāng)運(yùn)行 Java 應(yīng)用程序時(shí) , 這是 JVM 正常裝入類的缺省機(jī)制。

    4.??????? resolveClass 方法 resolveClass(Class c) 方法解析裝入的類,如果該類已經(jīng)被解析過那么將不做處理。當(dāng)調(diào)用 loadClass 方法時(shí) , 通過它的 resolve 參數(shù)決定是否要進(jìn)行解析。

    5.??????? findLoadedClass 方法 ? 當(dāng)調(diào)用 loadClass 方法裝入類時(shí) , 調(diào)用 findLoadedClass 方法來查看 ClassLoader 是否已裝入這個(gè)類 , 如果已裝入 , 那么返回 Class 對(duì)象 , 否則返回 NULL 。如果強(qiáng)行裝載已存在的類 , 將會(huì)拋出鏈接錯(cuò)誤。

    2.2 ????????? 裝載的應(yīng)用

    一般來說,我們實(shí)現(xiàn)自定義的 ClassLoader 需要繼承抽象類 java.lang.ClassLoader ,其中必須實(shí)現(xiàn)的方法是 loadClass(String name) ,對(duì)于這個(gè)方法需要實(shí)現(xiàn)如下操作:

    (1) 確認(rèn)類的名稱;

    (2) 檢查請(qǐng)求要裝載的類是否已經(jīng)被裝載;

    (3) 檢查請(qǐng)求加載的類是否是系統(tǒng)類;

    (4) 嘗試從類裝載器的存儲(chǔ)區(qū)獲取所請(qǐng)求的類;

    (5) 在虛擬機(jī)中定義所請(qǐng)求的類;

    (6) 解析所請(qǐng)求的類;

    (7) 返回所請(qǐng)求的類。

    所有的 Java 虛擬機(jī)都包括一個(gè)內(nèi)置的類裝載器,這個(gè)內(nèi)置的類庫裝載器被稱為根裝載器 (bootstrap ClassLoader) 。根裝載器的特殊之處是它只能夠裝載基本的 Java 類,如 rt.jar 中的 class 。當(dāng)應(yīng)用程序可以使用用戶自定義的 ClassLoader 來加載特定 ClassPath 下的類。下面的例子是 JDK5.0 URLClassLoader 的實(shí)現(xiàn)。

    public class URLClassLoader extends SecureClassLoader {

    ……

    protected Class<?> findClass(final String name)

    ?????? ?throws ClassNotFoundException

    ??? {

    ?????? try {

    ?????? ??? return (Class)

    ????????????? AccessController.doPrivileged(new PrivilegedExceptionAction() {

    ????????????? ??? public Object run() throws ClassNotFoundException {

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 由類的全限定名得到物理路徑

    ???????????????????? String path = name.replace('.', '/').concat(".class");

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// URLs ClassPath 中取得相應(yīng)的字節(jié)碼

    ???????????????????? Resource res = ucp.getResource(path, false);

    ???????????????????? if (res != null) {

    ???????????????????? ??? try {

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// Java 字節(jié)碼創(chuàng)建一個(gè) Class 對(duì)象

    ??????????????????????????? return defineClass(name, res);

    ???????????????????? ??? } catch (IOException e) {

    ??????????????????????????? throw new ClassNotFoundException(name, e);

    ???????????????????? ??? }

    ???????????????????? } else {

    ???????????????????? ??? throw new ClassNotFoundException(name);

    ???????????????????? }

    ????????????? ??? }

    ????????????? }, acc);

    ?????? } catch (java.security.PrivilegedActionException pae) {

    ?????? ??? throw (ClassNotFoundException) pae.getException();

    ?????? }

    ??? }

    ……

    }

    ?

    2.3 ????????? Java 虛擬機(jī)的類裝載原理

    前面我們已經(jīng)知道,一個(gè) Java 應(yīng)用程序使用兩種類型的類裝載器:根裝載器 (bootstrap) 和用戶定義的裝載器 (user-defined) 。根裝載器是 Java 虛擬機(jī)實(shí)現(xiàn)的一部分。根裝載器以某種默認(rèn)的方式將類裝入,包括 Java API 的類。在運(yùn)行期間,一個(gè) Java 程序能使用用戶自己定義的類裝載器。根裝載器是虛擬機(jī)固有的一部分,而用戶定義的類裝載器則不是,它是用 Java 語言寫的,被編譯成 class 文件之后然后再被裝入到虛擬機(jī),并像其它的任何對(duì)象一樣可以被實(shí)例化。 Java 類裝載器的體系結(jié)構(gòu)如下所示:

    Java 的類裝載的體系結(jié)構(gòu)

    Java 的類裝載模型是一種代理 (delegation) 模型。當(dāng) JVM 要求類裝載器 CL(ClassLoader) 裝載一個(gè)類時(shí) ,CL 首先將這個(gè)類裝載請(qǐng)求轉(zhuǎn)發(fā)給他的父裝載器。只有當(dāng)父裝載器沒有裝載并無法裝載這個(gè)類時(shí) ,CL 才獲得裝載這個(gè)類的機(jī)會(huì)。這樣 , 所有類裝載器的代理關(guān)系構(gòu)成了一種樹狀的關(guān)系。樹的根是類的根裝載器 (bootstrap ClassLoader) , JVM 中它以 "null" 表示。除根裝載器以外的類裝載器有且僅有一個(gè)父裝載器。在創(chuàng)建一個(gè)裝載器時(shí) , 如果沒有顯式地給出父裝載器 , 那么 JVM 將默認(rèn)系統(tǒng)裝載器為其父裝載器。 Java 的基本類裝載器代理結(jié)構(gòu)如圖 2 所示:

    Java 類裝載的代理結(jié)構(gòu)

    下面針對(duì)各種類裝載器分別進(jìn)行詳細(xì)的說明。

    (Bootstrap) 裝載器:該裝載器沒有父裝載器,它是 JVM 實(shí)現(xiàn)的一部分,從 sun.boot.class.path 裝載運(yùn)行時(shí)庫的核心代碼。

    ?

    擴(kuò)展 (Extension) 裝載器:繼承的父裝載器為根裝載器,不像根裝載器可能與運(yùn)行時(shí)的操作系統(tǒng)有關(guān),這個(gè)類裝載器是用純 Java 代碼實(shí)現(xiàn)的,它從 java.ext.dirs ( 擴(kuò)展目錄 ) 中裝載代碼。

    系統(tǒng) (System or Application) 裝載器:裝載器為擴(kuò)展裝載器,我們都知道在安裝 JDK 的時(shí)候要設(shè)置環(huán)境變量 (CLASSPATH ) ,這個(gè)類裝載器就是從 java.class.path(CLASSPATH 環(huán)境變量 ) 中裝載代碼的,它也是用純 Java 代碼實(shí)現(xiàn)的,同時(shí)還是用戶自定義類裝載器的缺省父裝載器。

    小應(yīng)用程序 (Applet) 裝載器:父裝載器為系統(tǒng)裝載器,它從用戶指定的網(wǎng)絡(luò)上的特定目錄裝載小應(yīng)用程序代碼。

    在設(shè)計(jì)一個(gè)類裝載器的時(shí)候,應(yīng)該滿足以下兩個(gè)條件:

    對(duì)于相同的類名,類裝載器所返回的對(duì)象應(yīng)該是同一個(gè)類對(duì)象

    如果類裝載器 CL1 將裝載類 C 的請(qǐng)求轉(zhuǎn)給類裝載器 CL2 ,那么對(duì)于以下的類或接口, CL1 CL2 應(yīng)該返回同一個(gè)類對(duì)象:

    a) ?S C 的直接超類;

    b) ?S C 的直接超接口;

    c) ?S C 的成員變量的類型;

    d) ?S C 的成員方法或構(gòu)建器的參數(shù)類型;

    e) ?S C 的成員方法的返回類型。

    每個(gè)已經(jīng)裝載到 JVM 中的類對(duì)象都含有裝載它的類裝載器的信息。 Class 類的方法 getClassLoader 可以得到裝載這個(gè)類的類裝載器。一個(gè)類裝載器認(rèn)識(shí)的類包括它的父裝載器認(rèn)識(shí)的類和它自己裝載的類,由此可見類裝載器認(rèn)識(shí)的類是它自己裝載的類的超集。注意,我們可以得到類裝載器的有關(guān)的信息,但是已經(jīng)裝載到 JVM 中的類是不能更改它的類裝載器的。

    Java 中的類的裝載過程也就是代理裝載的過程。比如: Web 瀏覽器中的 JVM 需要裝載一個(gè)小應(yīng)用程序 TestApplet JVM 調(diào)用小應(yīng)用程序裝載器 ACL(Applet ClassLoader) 來完成裝載。 ACL 首先請(qǐng)求它的父裝載器 , 即系統(tǒng)裝載器裝載 TestApplet 是否裝載了這個(gè)類,由于 TestApplet 不在系統(tǒng)裝載器的裝載路徑中 , 所以系統(tǒng)裝載器沒有找到這個(gè)類 , 也就沒有裝載成功。接著 ACL 自己裝載 TestApplet ACL 通過網(wǎng)絡(luò)成功地找到了 TestApplet.class 文件并將它導(dǎo)入到了 JVM 中。在裝載過程中 , JVM 發(fā)現(xiàn) TestAppet 是從超類 java.applet.Applet 繼承的。所以 JVM 再次調(diào)用 ACL 來裝載 java.applet.Applet 類。 ACL 又再次按上面的順序裝載 Applet , 結(jié)果 ACL 發(fā)現(xiàn)他的父裝載器已經(jīng)裝載了這個(gè)類 , 所以 ACL 就直接將這個(gè)已經(jīng)裝載的類返回給了 JVM , 完成了 Applet 類的裝載。接下來 ,Applet 類的超類也一樣處理。最后 , TestApplet 及所有有關(guān)的類都裝載到了 JVM 中。

    2.4 ????????? 總結(jié)

    ??? 類的動(dòng)態(tài)裝載機(jī)制是JVM的一項(xiàng)核心技術(shù), 也是容易被忽視而引起很多誤解的地方。本文介紹了JVM中類裝載的原理、實(shí)現(xiàn)以及應(yīng)用,分析了ClassLoader的結(jié)構(gòu)、用途以及如何利用自定義的ClassLoader裝載并執(zhí)行Java類,希望能使大家對(duì)JVM中的類裝載有一個(gè)比較深入的理解。

    posted on 2006-05-21 23:51 迷途書童 閱讀(2895) 評(píng)論(0)  編輯  收藏 所屬分類: 深入JVM


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲国产成人久久综合一 | 久久久久久久亚洲Av无码| 亚洲无码在线播放| MM131亚洲国产美女久久| 亚洲成人一区二区| 亚洲欧洲国产成人综合在线观看 | 免费观看的毛片大全| 亚洲视频免费观看| 最近高清中文字幕无吗免费看| 最近的中文字幕大全免费8| 4虎1515hh永久免费| 精品久久8x国产免费观看| 91成人免费观看网站| 欧美男同gv免费网站观看| 热久久精品免费视频| 国产无遮挡吃胸膜奶免费看视频 | 最近中文字幕mv免费高清电影| 好先生在线观看免费播放| 在线免费不卡视频| 亚洲AV成人精品日韩一区18p| 国产精品V亚洲精品V日韩精品| 亚洲精品乱码久久久久久久久久久久| 久久国产精品免费看| 日本免费人成网ww555在线| 永久在线免费观看| 免费看香港一级毛片| 亚洲国产精品尤物yw在线| 亚洲啪啪综合AV一区| 亚洲天堂一区二区| 亚洲jizzjizz在线播放久| 亚洲国产成人久久综合| 又粗又长又爽又长黄免费视频| 中文字幕免费在线观看动作大片| 国产va在线观看免费| 免费精品国偷自产在线在线| 国产又黄又爽又猛的免费视频播放 | 亚洲色一区二区三区四区| 久久久久亚洲av无码专区| 亚洲国产成人精品青青草原| 噜噜综合亚洲AV中文无码| 精品久久久久久无码免费|