天下難事,必作于易;天下大事,必作于細(xì)
          如果我有方向,那就是遠(yuǎn)方
          posts - 11,comments - 8,trackbacks - 0

          轉(zhuǎn)載自http://blog.csdn.net/yuekun1172006/archive/2007/06/02/1634878.aspx

          類(lèi)裝入器是 JVM 用來(lái)裝入類(lèi)的類(lèi),它對(duì)于 Java 編程是非常重要的一個(gè)概念。一般情況下,程序員在編寫(xiě)程序的時(shí)候都可以忽略類(lèi)裝入器的存在性。但是對(duì)于服務(wù)器端編程或者是一些特殊情況下時(shí)候,深入了解類(lèi)裝入器的機(jī)制以及其在不同情況下的實(shí)現(xiàn)還是非常必要的。

          首先,當(dāng)一個(gè) JVM 啟動(dòng)的時(shí)候,Java 缺省開(kāi)始使用三個(gè)類(lèi)裝入器。它們分別是:

          • 引導(dǎo)(Bootstrap)類(lèi)裝入器;
          • 擴(kuò)展(Extension)類(lèi)裝入器;
          • 系統(tǒng)(System)類(lèi)裝入器;

          它們分別實(shí)現(xiàn)如下的功能:

          • 引導(dǎo)類(lèi)裝入器是用本地代碼實(shí)現(xiàn)的類(lèi)裝入器。它負(fù)責(zé)將 <Java_Runtime_Home>/lib 下面的類(lèi)庫(kù)加載到內(nèi)存中。
          • 擴(kuò)展類(lèi)裝入器是由 Sun 的 ExtClassLoader 實(shí)現(xiàn)的。它負(fù)責(zé)將 < Java_Runtime_Home >/lib/ext 或者由系統(tǒng)變量 java.ext.dir 指定位置中的類(lèi)庫(kù)加載到內(nèi)存中。
          • 系統(tǒng)類(lèi)裝入器又叫應(yīng)用程序類(lèi)裝入器,是由 Sun 的 AppClassLoader 實(shí)現(xiàn)的。它負(fù)責(zé)將系統(tǒng)類(lèi)路徑(CLASSPATH)中指定的類(lèi)庫(kù)加載到內(nèi)存中。

          當(dāng)應(yīng)用程序需要加載某個(gè)類(lèi)到內(nèi)存中的時(shí)候,類(lèi)裝入器是如何工作的呢?這就設(shè)計(jì)到類(lèi)裝入器的一個(gè)重要方面:代理機(jī)制。每一個(gè)類(lèi)裝入器,除了引導(dǎo)類(lèi)裝入器以外,都有一個(gè)父類(lèi)裝入器。對(duì)于系統(tǒng)缺省定義的三個(gè)類(lèi)裝入器,引導(dǎo)類(lèi)裝入器是擴(kuò)展類(lèi)裝入器的父類(lèi)裝入器,而擴(kuò)展類(lèi)裝入器是系統(tǒng)類(lèi)裝入器的父類(lèi)裝入器。當(dāng)然,應(yīng)用程序也可以使用自己的類(lèi)裝入器來(lái)使用特定的方法來(lái)裝載類(lèi),因此,整個(gè)系統(tǒng)中的類(lèi)裝入器就形成一個(gè)樹(shù)狀結(jié)構(gòu)。

          當(dāng)使用某個(gè)類(lèi)裝入器來(lái)試圖裝載某個(gè)類(lèi)的時(shí)候,該類(lèi)裝入器會(huì)首先使用其父類(lèi)裝入器來(lái)試圖裝載該類(lèi)。對(duì)于每一個(gè)裝載進(jìn)來(lái)的類(lèi),JVM 都會(huì)給其分配一個(gè)唯一的 ID。因此,不同類(lèi)裝入器可以裝載同一個(gè)類(lèi)到 JVM 中。例如,對(duì)于如下圖結(jié)構(gòu)的 ClassLoaderAClassLoaderB


          圖 1 類(lèi)裝入器的結(jié)構(gòu)
          圖 1 類(lèi)裝入器的結(jié)構(gòu)

          假設(shè)類(lèi) C 在系統(tǒng)類(lèi)裝入器指定的類(lèi)路徑中,則無(wú)論是使用 ClassLoaderA 還是使用 ClassLoaderB,都只會(huì)得到同樣一個(gè)類(lèi) C

          但是如果類(lèi) C 分別在 ClassLoaderA 以及 ClassLoaderB 指定的類(lèi)庫(kù)中,則使用 ClassLoaderA 得到到類(lèi) C 實(shí)例會(huì)不同于 ClassLoaderB 得到的類(lèi) C 實(shí)例。盡管兩個(gè)類(lèi)裝入器在同一個(gè) JVM 中。

          上面的類(lèi)裝入器的向上代理結(jié)構(gòu)看上去很完美了,但是,當(dāng)系統(tǒng)變得復(fù)雜的時(shí)候,就還是顯得不夠用了。

          例如,當(dāng) Java 引入了 JNDI 以后,JNDI 核心部分是通過(guò)引導(dǎo) 類(lèi)裝入器在 JVM 啟動(dòng)的時(shí)候裝載進(jìn)入 JVM 的。而 JDNI 核心部分是通過(guò)配置信息來(lái)在運(yùn)行時(shí)候裝載定義在用戶(hù)的類(lèi)路徑中的特定類(lèi)來(lái)完成特定需要。而這是上面定義的類(lèi)裝入器的向上代理模式所不能支持的。

          為了解決這個(gè)問(wèn)題,Java 2 中引入了線程上下文(Thread Content)類(lèi)裝入器的概念,每一個(gè)線程有一個(gè) Context 類(lèi)裝入器。這個(gè) Context 類(lèi)裝入器是通過(guò)方法 Thread.setContextClassLoader() 設(shè)置的,如果當(dāng)前線程在創(chuàng)建后沒(méi)有調(diào)用這個(gè)方法設(shè)置 Context 類(lèi)裝入器,則當(dāng)前線程從他的父線程繼承 Context 類(lèi)裝入器。如果整個(gè)應(yīng)用都沒(méi)有設(shè)置 Context 類(lèi)裝入器,則系統(tǒng)類(lèi)裝入器被設(shè)置為所有線程的 Context 類(lèi)裝入器。

          對(duì)于我們上面所說(shuō) JNDI 的情況,引導(dǎo) 類(lèi)裝入器裝載進(jìn)入的 JNDI 核心類(lèi)會(huì)使用 Context 類(lèi)裝入器來(lái)裝載其所需要的 JNDI 實(shí)現(xiàn)類(lèi),而不是將該裝載任務(wù)代理給其父類(lèi)裝入器來(lái)完成。這樣,就解決了上面的問(wèn)題。可以認(rèn)為 Context 類(lèi)裝入器在傳統(tǒng)的 Java 向上代理機(jī)制上打開(kāi)了一個(gè)后門(mén)。Context 類(lèi)裝入器在 J2EE 中使用的很廣泛,比如 Java 命名服務(wù)(JNDI),Java API for XML Parsing(JAXP)(注:在 Java1.4 中 JAXP 才作為 Java 的核心類(lèi)的一部分,它才開(kāi)始使用 Context 類(lèi)裝入器來(lái)加載不同的實(shí)現(xiàn)類(lèi))等。

          簡(jiǎn)單而言,Java 中的類(lèi)裝入器就是上面幾種,但是,在具體使用中,還是有很多變化,我們下面分別對(duì)于一些情況進(jìn)行說(shuō)明。

          posted on 2007-11-22 10:51 flyepp 閱讀(573) 評(píng)論(0)  編輯  收藏

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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 杂多县| 滨州市| 彭水| 武川县| 昆山市| 星座| 宁波市| 沾益县| 汨罗市| 淮南市| 交口县| 昌平区| 大荔县| 江都市| 祁东县| 南汇区| 庆元县| 淳化县| 徐闻县| 杨浦区| 铜川市| 海宁市| 镇康县| 青州市| 长武县| 广宗县| 孟连| 东乌珠穆沁旗| 建湖县| 玉山县| 京山县| 吴川市| 仁化县| 南召县| 安陆市| 永康市| 唐山市| 班玛县| 泸西县| 曲松县| 云龙县|