深入了解類加載器_第1頁(yè)
深入了解類加載器_第2頁(yè)
深入了解類加載器_第3頁(yè)
已閱讀5頁(yè),還剩7頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、深入探討Java類加載器類加載器是Java語(yǔ)言的一個(gè)創(chuàng)新,也是 Java語(yǔ)言流行的重要原因之一。它 使得Java類可以被動(dòng)態(tài)加載到Java虛擬機(jī)中并執(zhí)行。類加載器從JDK 1.0就出現(xiàn)了,最初是為了滿足Java Applet的需要而開(kāi)發(fā)出來(lái)的。Java Applet需 要從遠(yuǎn)程下載Java類文件到瀏覽器中并執(zhí)行?,F(xiàn)在類加載器在Web容器和OSGi中得到了廣泛的使用。一般來(lái)說(shuō),Java應(yīng)用的開(kāi)發(fā)人員不需要直接同類 加載器進(jìn)行交互。Java虛擬機(jī)默認(rèn)的行為就已經(jīng)足夠滿足大多數(shù)情況的需求了。 不過(guò)如果遇到了需要與類加載器進(jìn)行交互的情況,而對(duì)類加載器的機(jī)制又不是很 了解的話,就很容易花大量的時(shí)間去調(diào)試

2、ClassNotFou ndExceptio n和NoClassDefFoundError等異常。本文將詳細(xì)介紹 Java的類加載器,幫助讀者深刻理解Java語(yǔ)言中的這個(gè)重要概念。下面首先介紹一些相關(guān)的基本 概念。類加載器基本概念顧名思義,類加載器(class loader )用來(lái)加載Java類到Java虛擬機(jī)中。一 般來(lái)說(shuō),Java虛擬機(jī)使用Java類的方式如下:Java源程序(.java文件)在 經(jīng)過(guò)Java編譯器編譯之后就被轉(zhuǎn)換成 Java字節(jié)代碼(.class文件)。類加 載器負(fù)責(zé)讀取Java字節(jié)代碼,并轉(zhuǎn)換成類的一個(gè)實(shí)例。每個(gè)這樣的實(shí)例用來(lái)表示一個(gè)Java類。通過(guò)此實(shí)例的newlns

3、tance()方法就可以創(chuàng)建出該類的一個(gè)對(duì)象。實(shí)際的情況可能更加復(fù)雜,比如Java字節(jié)代碼可能是通過(guò)工具動(dòng)態(tài)生成的,也可能是通過(guò)網(wǎng)絡(luò)下載的?;旧纤械念惣虞d器都是java.la ng.ClassLoader類的一個(gè)實(shí)例。下面詳細(xì)介紹這個(gè)Java類。javaan g.ClassLoader類介紹java.la ng.ClassLoader類的基本職責(zé)就是根據(jù)一個(gè)指定的類的名稱,找到或者生成其對(duì)應(yīng)的字節(jié)代碼,然后從這些字節(jié)代碼中定義出一個(gè)Java類,即類的一個(gè)實(shí)例。除此之外,ClassLoader還負(fù)責(zé)加載Java應(yīng)用所需的資源,如圖像文件和配置文件等。不過(guò)本文只討論其加載類的 功能。為了完成加

4、載類的這個(gè)職責(zé),ClassLoader 提供了一系列的方法,比較 重要的方法如 所示。關(guān)于這些方法的細(xì)節(jié)會(huì)在下面進(jìn)行介紹。表1. ClassLoader中與加載類相關(guān)的方法方法說(shuō)明getPare nt()返回該類加載器的父類加載器。方法說(shuō)明loadClass(Stri ng n ame)加載名稱為name的類,返回的結(jié)果是 java.la ng.Class類的實(shí)例。fin dClass(Stri ng n ame)查找名稱為name的類,返回的結(jié)果是 java.la ng.Class類的實(shí)例。fin dLoadedClass(Stri ng n ame)查找名稱為name的已經(jīng)被加載過(guò)的類,返

5、回的結(jié)果是 java.la ng.Class類的實(shí)例。defi neClass(Stri ng n ame, byte把字節(jié)數(shù)組b中的內(nèi)容轉(zhuǎn)換成Java類,返回的結(jié)果b, int off, int len)是final的。resolveClass(Class c)鏈接指定的Java類。對(duì)于中給出的方法,表示類名稱的name參數(shù)的值是類的二進(jìn)制名稱。需要注 意的是內(nèi)部類的表示,如,做進(jìn)一步的說(shuō)明。下面介紹類加載器的樹狀組織結(jié) 構(gòu)。類加載器的樹狀組織結(jié)構(gòu)Java中的類加載器大致可以分成兩類,一類是系統(tǒng)提供的,另外一類則是由Java應(yīng)用開(kāi)發(fā)人員編寫的。系統(tǒng)提供的類加載器主要有下面三個(gè):引導(dǎo)類加載器(

6、bootstrap class loader ):它用來(lái)加載 Java的核心庫(kù),是用原生代碼來(lái)實(shí)現(xiàn)的,并不繼承自*擴(kuò)展類加載器(extensions class loader ):它用來(lái)加載 Java的擴(kuò)展庫(kù)。Java虛擬機(jī)的實(shí)現(xiàn)會(huì)提供一個(gè)擴(kuò)展庫(kù)目錄。該類加載器在此目錄里面查找并加載 Java類。系統(tǒng)類加載器(system class loader ):它根據(jù)Java應(yīng)用的類路徑(CLASSPATH )來(lái)加載Java類。一般來(lái)說(shuō),Java應(yīng)用的類都是 由它來(lái)完成加載的。可以通過(guò) ClassLoader.getSystemClassLoader()來(lái)獲取它。除了系統(tǒng)提供的類加載器以外,開(kāi)發(fā)人員可

7、以通過(guò)繼承,以滿足一些特殊的需求。除了引導(dǎo)類加載器之外,所有的類加載器都有一個(gè)父類加載器。通過(guò)中給出的getParent()方法可以得到。對(duì)于系統(tǒng)提供的類加載器來(lái)說(shuō),系統(tǒng)類加載器的父類加載器是擴(kuò)展類加載器,而擴(kuò)展類加載器的父類加載器是引導(dǎo)類加載器; 對(duì)于開(kāi)發(fā)人員編寫的類加載器來(lái)說(shuō),其父類加載器是加載此類加載器Java類的類加載器。因?yàn)轭惣虞d器 Java類如同其它的Java類一樣,也是要由類加 載器來(lái)加載的。一般來(lái)說(shuō),開(kāi)發(fā)人員編寫的類加載器的父類加載器是系統(tǒng)類加載 器。類加載器通過(guò)這種方式組織起來(lái),形成樹狀結(jié)構(gòu)。樹的根節(jié)點(diǎn)就是引導(dǎo)類加 載器。中給出了一個(gè)典型的類加載器樹狀組織結(jié)構(gòu)示意圖,其中的箭

8、頭指向的是父類加載器。圖1.類加載器樹狀組織結(jié)構(gòu)示意圖演示了類加載器的樹狀組織結(jié)構(gòu)。 清單1.演示類加載器的樹狀組織結(jié)構(gòu) public class ClassLoaderTree public static void main (Stri ng args) ClassLoader loader =;while (loader != n ull) loader = loader.getPare nt();每個(gè)Java類都維護(hù)著一個(gè)指向定義它的類加載器的引用,通 過(guò)getClassLoader() 方法就可以獲取到此引用。中通過(guò)遞歸調(diào)用 getPare nt()方法來(lái)輸出全部的父類加載器。的運(yùn)行結(jié)

9、果如所示清單2.演示類加載器的樹狀組織結(jié)構(gòu)的運(yùn)行結(jié)果如所示,第一個(gè)輸出的是ClassLoaderTree類的類加載器,即系統(tǒng)類加載器。它是;第二個(gè)輸出的是擴(kuò)展類加載器,是,這是由于有些JDK的實(shí)現(xiàn)對(duì)于父類加載器是引導(dǎo)類加載器的情況,getParent()方法返回null 。在了解了類加載器的樹狀組織結(jié)構(gòu)之后,下面介紹類加載器的代理模式。類加載器的代理模式類加載器在嘗試自己去查找某個(gè)類的字節(jié)代碼并定義它時(shí),會(huì)先代理給其父類加載器,由父類加載器先去嘗試加載這個(gè)類,依次類推。在介紹代理模式背后的動(dòng)機(jī)之前,首先需要說(shuō)明一下Java虛擬機(jī)是如何判定兩個(gè)Java類是相同的。Java虛擬機(jī)不僅要看類的全名是

10、否相同,還要看加載此類的類加載器是否一樣。 只有兩者都相同的情況,才認(rèn)為兩個(gè)類是相同的。即便是同樣的字節(jié)代碼,被不 同的類加載器加載之后所得到的類,也是不同的。比如一個(gè)Java類,編譯之后生成了字節(jié)代碼文件Sample.class 。兩個(gè)不同的類加載器ClassLoaderA 和ClassLoaderB分別讀取了這個(gè)Sample.class文件,并定義出兩個(gè)Java虛擬機(jī)來(lái)說(shuō),它們是不同的類。試圖對(duì)這兩個(gè)類的對(duì)象進(jìn)行相互賦值, 會(huì)拋出運(yùn)行時(shí)異常ClassCastException 。下面通過(guò)示例來(lái)具體說(shuō)明。中給出 了 Java 類 清單3.類package com.example;public

11、 class Sample private Sample in sta nee;public void setSample(Object in sta nee) this.i nsta nee = (Sample) in sta nee;如所示,setSample 接受一個(gè),并且會(huì)把該參數(shù)強(qiáng)制轉(zhuǎn)換成Java類是否相同的代碼如所示。清單4.測(cè)試Java類是否相同public void testClassIde ntity() Stri ng classDataRootPath = C:workspaceClassloaderclassData;FileSystemClassLoader fscl

12、l = new FileSystemClassLoader(classDataRootPath);FileSystemClassLoader fscl2 = new FileSystemClassLoader(classDataRootPath);Stri ng className =;try Class class1 = fscl1.loadClass(className);Object obj1 = class1. newIn sta nce();Class class2 = fscl2 .l oadClass(className);Object obj2 = class2 .newIn

13、sta nce();Method setSampleMethod = class1.getMethod(setSample,;setSampleMethod.invoke(obj1, obj2); catch (Excepti on e) e.pri ntStackTrace();中使用了類FileSystemClassLoader 的兩個(gè)不同實(shí)例來(lái)分別加載類,得到 了兩個(gè)不同的,接著通過(guò)newInstance()方法分別生成了兩個(gè)類的對(duì)象obj1和obj2,最后通過(guò)Java的反射API在對(duì)象obj1上調(diào)用方法setSample , 試圖把對(duì)象obj2賦值給obj1內(nèi)部的instanee 對(duì)象

14、。的運(yùn)行結(jié)果如 所示。 清單5.測(cè)試Java類是否相同的運(yùn)行結(jié)果at Method)atatatatatCaused by:cannot be cast toat.6 more從給出的運(yùn)行結(jié)果可以看到,運(yùn)行時(shí)拋出了objl和obj2的類的名字相同,但是這兩個(gè)類是由不同的類加載器實(shí)例來(lái)加載的,因此不被Java虛擬機(jī)認(rèn)為是相同的。了解了這一點(diǎn)之后,就可以理解代理模式的設(shè)計(jì)動(dòng)機(jī)了。代理模式是為了保證 Java核心庫(kù)的類型安全。所有Java應(yīng)用都至少需要引用,也就是說(shuō)在運(yùn)行的時(shí)候,Java虛擬機(jī)中。如果這個(gè)加載過(guò)程由Java應(yīng)用自己的類加載器來(lái)完成的話,很可能就存在多個(gè)版本的,而且這些類之間是不兼容的

15、。通過(guò)代理模 式,對(duì)于Java核心庫(kù)的類的加載工作由引導(dǎo)類加載器來(lái)統(tǒng)一完成,保證了 Java應(yīng)用所使用的都是同一個(gè)版本的Java核心庫(kù)的類,是互相兼容的。不同的類加載器為相同名稱的類創(chuàng)建了額外的名稱空間。相同名稱的類可以并存 在Java虛擬機(jī)中,只需要用不同的類加載器來(lái)加載它們即可。不同類加載器 加載的類之間是不兼容的,這就相當(dāng)于在 Java虛擬機(jī)內(nèi)部創(chuàng)建了一個(gè)個(gè)相互 隔離的Java類空間。這種技術(shù)在許多框架中都被用到,后面會(huì)詳細(xì)介紹。下面具體介紹類加載器加載類的詳細(xì)過(guò)程。加載類的過(guò)程在前面介紹類加載器的代理模式的時(shí)候,提到過(guò)類加載器會(huì)首先代理給其它類加 載器來(lái)嘗試加載某個(gè)類。這就意味著真正完

16、成類的加載工作的類加載器和啟動(dòng)這 個(gè)加載過(guò)程的類加載器,有可能不是同一個(gè)。真正完成類的加載工作是通過(guò)調(diào) 用defin eClass來(lái)實(shí)現(xiàn)的;而啟動(dòng)類的加載過(guò)程是通過(guò)調(diào)用loadClass 來(lái)實(shí)現(xiàn)的。前者稱為一個(gè)類的定義加載器(defining loader ),后者稱為初始加載器(initiating loader )。在Java虛擬機(jī)判斷兩個(gè)類是否相同的時(shí)候,使用的是類 的定義加載器。也就是說(shuō),哪個(gè)類加載器啟動(dòng)類的加載過(guò)程并不重要,重要的是最終定義這個(gè)類的加載器。兩種類加載器的關(guān)聯(lián)之處在于:一個(gè)類的定義加載器 是它引用的其它類的初始加載器。如類,則由類方法loadClass() 拋出的是;方

17、法defineClass()拋出的是類加載器在成功加載某個(gè)類之后,會(huì)把得到的,類加載器會(huì)直接使用緩存的類的實(shí)例,而不會(huì)嘗試再次加載。也就是說(shuō),對(duì)于一個(gè)類加載器實(shí)例來(lái)說(shuō),相同全 名的類只加載一次,即loadClass方法不會(huì)被重復(fù)調(diào)用。下面討論另外一種類加載器:線程上下文類加載器。線程上下文類加載器線程上下文類加載器(con text class loader )是從JDK 1.2開(kāi)始引入的。類 getContextClassLoader()和setCo ntextClassLoader(ClassLoader cl)用來(lái)獲取和設(shè)置線程的上下文類加載器。如果沒(méi)有通過(guò) setCo ntextCla

18、ssLoader(ClassLoader cl)方法進(jìn)行設(shè)置的話,線程將繼承其父線程的上下文類加載器。Java應(yīng)用運(yùn)行的初始線程的上下文類加載器是系統(tǒng)類加載器。在線程中運(yùn)行的代碼可以通過(guò)此類加載器來(lái)加載類和資源。前面提到的類加載器的代理模式并不能解決Java應(yīng)用開(kāi)發(fā)中會(huì)遇到的類加載器的全部問(wèn)題。Java提供了很多服務(wù)提供者接口 ( Service Provider In terface , SPI),允許第三方為這些接口提供實(shí)現(xiàn)。常見(jiàn)的SPI有JDBC、JCE、JNDI、JAXP和JBI等。這些 SPI的接口由Java核心庫(kù)來(lái)提供,如 JAXP的SPI 接口定義包含在 SPI的實(shí)現(xiàn)代碼很可能是

19、作為 Java應(yīng)用所依賴的jar包被 包含進(jìn)來(lái),可以通過(guò)類路徑(CLASSPATH )來(lái)找到,如實(shí)現(xiàn)了 JAXP SPI的所 包含的jar包。SPI接口中的代碼經(jīng)常需要加載具體的實(shí)現(xiàn)類。如JAXP中的 newInstance()方法用來(lái)生成一個(gè)新的 DocumentBuilderFactory的實(shí)例。這里的實(shí)例的真正的類是繼承自,由SPI的實(shí)現(xiàn)所提供的。如在Apache Xerces中,實(shí)現(xiàn)的類是,SPI的接口是Java核心庫(kù)的一部分,是由引導(dǎo)類 加載器來(lái)加載的;SPI實(shí)現(xiàn)的Java類一般是由系統(tǒng)類加載器來(lái)加載的。引導(dǎo) 類加載器是無(wú)法找到 SPI的實(shí)現(xiàn)類的,因?yàn)樗患虞d Java的核心庫(kù)。它也

20、不 能代理給系統(tǒng)類加載器,因?yàn)樗窍到y(tǒng)類加載器的祖先類加載器。也就是說(shuō),類 加載器的代理模式無(wú)法解決這個(gè)問(wèn)題。線程上下文類加載器正好解決了這個(gè)問(wèn)題。如果不做任何的設(shè)置,Java應(yīng)用的線程的上下文類加載器默認(rèn)就是系統(tǒng)上下文類加載器。在SPI接口的代碼中使用線程上下文類加載器,就可以成功的加載到SPI實(shí)現(xiàn)的類。線程上下文類加載器在很多SPI的實(shí)現(xiàn)中都會(huì)用到。下面介紹另外一種加載類的方法:Class.forName 。Class.forNameClass.forName是一個(gè)靜態(tài)方法,同樣可以用來(lái)加載類。該方法有兩種形式:Class.forName(Stri ng n ame, boolea n i

21、n itialize, ClassLoader loader)和 Class.forName(String className)。第一種形式的參數(shù)name表示的是類的全名;initialize表示是否初始化類;loader 表示加載時(shí)使用的類加載器。第二種形式則相當(dāng)于設(shè)置了參數(shù)ini tialize 的值為true ,loader的值為當(dāng)前類的類加載器。Class.forName 的一個(gè)很常見(jiàn)的用法是在加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)的時(shí)候。如Class.forName).newlnstance()用來(lái)加載 Apache Derby 數(shù)據(jù)庫(kù)的驅(qū)動(dòng)。在介紹完類加載器相關(guān)的基本概念之后,下面介紹如何開(kāi)發(fā)自己的類加載

22、器。開(kāi)發(fā)自己的類加載器雖然在絕大多數(shù)情況下,系統(tǒng)默認(rèn)提供的類加載器實(shí)現(xiàn)已經(jīng)可以滿足需求。但是在某些情況下,您還是需要為應(yīng)用開(kāi)發(fā)出自己的類加載器。比如您的應(yīng)用通過(guò)網(wǎng)絡(luò)來(lái)傳輸Java類的字節(jié)代碼,為了保證安全性,這些字節(jié)代碼經(jīng)過(guò)了加密處 理。這個(gè)時(shí)候您就需要自己的類加載器來(lái)從某個(gè)網(wǎng)絡(luò)地址上讀取加密后的字節(jié)代 碼,接著進(jìn)行解密和驗(yàn)證,最后定義出要在Java虛擬機(jī)中運(yùn)行的類來(lái)。下面將通過(guò)兩個(gè)具體的實(shí)例來(lái)說(shuō)明類加載器的開(kāi)發(fā)。文件系統(tǒng)類加載器第一個(gè)類加載器用來(lái)加載存儲(chǔ)在文件系統(tǒng)上的Java字節(jié)代碼。完整的實(shí)現(xiàn)如所示。清單6.文件系統(tǒng)類加載器public class FileSystemClassLoade

23、r exte nds ClassLoader private String rootDir;public FileSystemClassLoader(String rootDir) this.rootDir = rootDir;protected Class fin dClass(Stri ng n ame) throws ClassNotFo un dExcepti on byte classData = getClassData (n ame);if (classData = n ull) throw new ClassNotFo un dExcepti on ();else retu r

24、n defi neClass (n ame, classData, 0, classData .len gth);private byte getClassData(String className) Stri ng path = classNameToPath(className);try In putStream ins = new FileI nputStream(path);ByteArrayOutputStream baos = new ByteArrayOutputStream();int bufferSize = 4096;byte buffer = new bytebuffer

25、Size;int bytesNumRead = 0;while (bytesNumRead = ins.read(buffer) != -1) baos.write(buffer, 0, bytesNumRead);retu rn baos.toByteArray(); catch (IOExcepti on e) e.pri ntStackTrace();return n ull;private Stri ng classNameToPath(Stri ng className) retu rn rootDir + File.separatorChar+ className.replace(

26、., File.separatorChar) + .class;如 所示,類FileSystemClassLoader繼承自類中列出的,一般來(lái)說(shuō),自己開(kāi)發(fā)的類加載器只需要覆寫fin dClass(Stri ng name)方法即可。fin dLoadedClass()方法來(lái)檢查該類是否已經(jīng)被加載過(guò);如果沒(méi)有加載過(guò)的話,會(huì)調(diào)用父類加載器的loadClass()方法來(lái)嘗試加載該類;如果父類加載器無(wú)法加載該類的話,就調(diào)用fin dClass()方法來(lái)查找該類。因此,為了保證類加載器都正確實(shí)現(xiàn)代理模式,在開(kāi)發(fā)自己的類加載器時(shí),最好不要覆 寫loadClass()方法,而是覆寫findClass()方法

27、。類FileSystemClassLoader 的findClass()方法首先根據(jù)類的全名在硬盤上查找類的字節(jié)代碼文件(.class文件),然后讀取該文件內(nèi)容,最后通 過(guò)defineClass()方法來(lái)把這些字節(jié)代碼轉(zhuǎn)換成網(wǎng)絡(luò)類加載器下面將通過(guò)一個(gè)網(wǎng)絡(luò)類加載器來(lái)說(shuō)明如何通過(guò)類加載器來(lái)實(shí)現(xiàn)組件的動(dòng)態(tài)更新。 即基本的場(chǎng)景是:Java字節(jié)代碼(.class)文件存放在服務(wù)器上,客戶端通過(guò) 網(wǎng)絡(luò)的方式獲取字節(jié)代碼并執(zhí)行。當(dāng)有版本更新的時(shí)候,只需要替換掉服務(wù)器上 保存的文件即可。通過(guò)類加載器可以比較簡(jiǎn)單的實(shí)現(xiàn)這種需求。類NetworkClassLoader負(fù)責(zé)通過(guò)網(wǎng)絡(luò)下載 Java類字節(jié)代碼并定義出J

28、ava類。它的實(shí)現(xiàn)與FileSystemClassLoader 類似。在通過(guò)NetworkClassLoader加載了某個(gè)版本的類之后,一般有兩種做法來(lái)使用它。第一種做法是使用Java反射API。另外一種做法是使用接口。需要注意的是, 并不能直接在客戶端代碼中引用從服務(wù)器上下載的類,因?yàn)榭蛻舳舜a的類加載器找不到這些類。使用Java反射API可以直接調(diào)用Java類的方法。而使用 接口的做法則是把接口的類放在客戶端中, 從服務(wù)器上加載實(shí)現(xiàn)此接口的不同版 本的類。在客戶端通過(guò)相同的接口來(lái)使用這些實(shí)現(xiàn)類。網(wǎng)絡(luò)類加載器的具體代碼見(jiàn)。在介紹完如何開(kāi)發(fā)自己的類加載器之后,下面說(shuō)明類加載器和 Web容器的關(guān)

29、系,類加載器與Web容器對(duì)于運(yùn)行在Java EE?容器中的 Web應(yīng)用來(lái)說(shuō),類加載器的實(shí)現(xiàn)方式與一般 的Java應(yīng)用有所不同。不同的 Web容器的實(shí)現(xiàn)方式也會(huì)有所不同。以 Apache Tomcat來(lái)說(shuō),每個(gè) Web應(yīng)用都有一個(gè)對(duì)應(yīng)的類加載器實(shí)例。該類加 載器也使用代理模式,所不同的是它是首先嘗試去加載某個(gè)類,如果找不到再代理給父類加載器。這與一般類加載器的順序是相反的。這是Java Servlet規(guī)范中的推薦做法,其目的是使得 Web應(yīng)用自己的類的優(yōu)先級(jí)高于 Web容器提 供的類。這種代理模式的一個(gè)例外是:Java核心庫(kù)的類是不在查找范圍之內(nèi)的。 這也是為了保證Java核心庫(kù)的類型安全。絕大

30、多數(shù)情況下,Web應(yīng)用的開(kāi)發(fā)人員不需要考慮與類加載器相關(guān)的細(xì)節(jié)。下 面給出幾條簡(jiǎn)單的原則:每個(gè) Web應(yīng)用自己的Java類文件和使用的庫(kù)的jar包,分別放在 WEB-INF/classes禾口 WEB-INF/lib 目錄下面。多個(gè)應(yīng)用共享的Java類文件和jar包,分別放在 Web容器指定的由所有 Web應(yīng)用共享的目錄下面。.當(dāng)出現(xiàn)找不到類的錯(cuò)誤時(shí),檢查當(dāng)前類的類加載器和當(dāng)前線程的上下文類加載器是否正確。在介紹完類加載器與 Web容器的關(guān)系之后,下面介紹它與OSGi的關(guān)系。類加載器與OSGiOSGi?是Java上的動(dòng)態(tài)模塊系統(tǒng)。它為開(kāi)發(fā)人員提供了面向服務(wù)和基于組件 的運(yùn)行環(huán)境,并提供標(biāo)準(zhǔn)的方

31、式用來(lái)管理軟件的生命周期。OSGi已經(jīng)被實(shí)現(xiàn)和部署在很多產(chǎn)品上,在開(kāi)源社區(qū)也得到了廣泛的支持。Eclipse就是基于OSGi技術(shù)來(lái)構(gòu)建的。OSGi中的每個(gè)模塊(bundle )都包含Java包和類。模塊可以聲明它所依賴的 需要導(dǎo)入(import)的其它模塊的 Java包和類(通過(guò)Import-Package ), 也可以聲明導(dǎo)出(export)自己的包和類,供其它模塊使用(通過(guò)Export-Package )。也就是說(shuō)需要能夠隱藏和共享一個(gè)模塊中的某些Java包和類。這是通過(guò) OSGi特有的類加載器機(jī)制來(lái)實(shí)現(xiàn)的。OSGi中的每個(gè)模塊 都有對(duì)應(yīng)的一個(gè)類加載器。它負(fù)責(zé)加載模塊自己包含的Java包和類。當(dāng)它需要加載Java核心庫(kù)的類時(shí)(以java開(kāi)頭的包和類),它會(huì)代理給父類加載器(通常是啟動(dòng)類加載器)來(lái)完成。當(dāng)它需要加載所導(dǎo)入的 Java類時(shí),它會(huì)代 理給導(dǎo)出此Java類的模塊來(lái)完成加載。模塊也可以顯式的聲明某些 Java包 和類,必須由父類加載器來(lái)加載。只需要設(shè)置系統(tǒng)屬性假設(shè)有兩個(gè)模塊bundleA和bundleB,它們都有自己對(duì)應(yīng)的類加載器

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論