?
與
C
或
C++
編寫的程序不同,
Java
程序并不是一個可執(zhí)行文件,而是由許多獨立的類文件組成,每一個文件對應(yīng)于一個
Java
類。此外,這些類文件并非立即全部都裝入內(nèi)存,而是根據(jù)程序需要裝入內(nèi)存。
ClassLoader
是
JVM
中將類裝入內(nèi)存的那部分。而且,
Java ClassLoader
就是用
Java
語言編寫的。這意味著創(chuàng)建您自己的
ClassLoader
非常容易,不必了解
JVM
的微小細(xì)節(jié)。
Java
的
classloader
不但可以使你運行本地得
class
類
,
你也可以定制
classloader
運行來自遠(yuǎn)程的字節(jié)代碼
.
ClassLoader
的基本目標(biāo)是對類的請求提供服務(wù)。當(dāng)
JVM
需要使用類時,它根據(jù)名稱向
ClassLoader
請求這個類,然后
ClassLoader
試圖返回一個表示這個類的
Class
對象。
通過覆蓋對應(yīng)于這個過程不同階段的方法,可以創(chuàng)建定制的
ClassLoader
。通常當(dāng)你需要動態(tài)加載資源的時候
,
你至少有三個
ClassLoader
可以選擇
:
1.??????
系統(tǒng)類加載器(應(yīng)用類加載器)
(system classloader or application classloader)
2.??????
當(dāng)前類加載器
3.??????
當(dāng)前線程類加載器
第一種
:
系統(tǒng)類加載器
系統(tǒng)類加載器
(system classloader).
這個類加載器處理
-classpath
下的類加載工作
,
可以通過
ClassLoader.getSystemClassLoader()
方法調(diào)用
.
ClassLoader
下所有的
getSystemXXX()
的靜態(tài)方法都是通過這個方法定義的
.
在你的代碼中
,
你應(yīng)該盡量少地調(diào)用這個方法
,
以其它的類加載器作為代理
.
否則你的代碼將只能工作在簡單的命令行應(yīng)用中
,
這個時候系統(tǒng)類加載器
(system classloader)
是
JVM
最后創(chuàng)建的類加載器
.
一旦你把代碼移到
EJB, Web
應(yīng)用或
Java Web Start
應(yīng)用中
,
一定會出問題
.
Class.loadClass( String name, boolean resolve );
name
參數(shù)指定了
JVM
需要的類的名稱,該名稱以包表示法表示,如
Foo
或
? java.lang.Object
。
resolve
參數(shù)告訴方法是否需要解析類。在準(zhǔn)備執(zhí)行類之前,應(yīng)考慮類解析。并不總是需要解析。如果
JVM
只需要知道該類是否存在或找出該類的超類,那么就不需要解析。
方法
defineClass
是
ClassLoader
的主要訣竅。
該方法接受由原始字節(jié)組成的數(shù)組并把它轉(zhuǎn)換成
Class
對象。原始數(shù)組包含如從文件系統(tǒng)或網(wǎng)絡(luò)裝入的數(shù)據(jù)。
defineClass
管理
JVM
的許多復(fù)雜、神秘和倚賴于實現(xiàn)的方面
--
它把字節(jié)碼分析成運行時數(shù)據(jù)結(jié)構(gòu)、校驗有效性等等。不必?fù)?dān)心,您無需親自編寫它。事實上,即使您想要這么做也不能覆蓋它,因為它已被標(biāo)記成最終的。
方法
findSystemClass
findSystemClass
方法從本地文件系統(tǒng)裝入文件。它在本地文件系統(tǒng)中尋找類文件,如果存在,就使用
defineClass
將原始字節(jié)轉(zhuǎn)換成
Class
對象,以將該文件轉(zhuǎn)換成類。當(dāng)運行
Java
應(yīng)用程序時,這是
JVM
正常裝入類的缺省機(jī)制
.
??
如果
ClassLoader
不能找到類,它會請求父代
ClassLoader
來執(zhí)行此項任務(wù)。所有
ClassLoaders
的根是系統(tǒng)
ClassLoader
,它會以缺省方式裝入類
--
即,從本地文件系統(tǒng)。
方法
findLoadedClass
充當(dāng)一個緩存
當(dāng)請求
loadClass
裝入類時,它調(diào)用該方法來查看
ClassLoader
是否已裝入這個類,這樣可以避免重新裝入已存在類所造成的麻煩。應(yīng)首先調(diào)用該方法。
讓我們看一下如何組裝所有方法。
loadClass
實現(xiàn)示例執(zhí)行以下步驟:
(這里,我們沒有指定生成類文件是采用了哪種技術(shù),它可以是從
Net
上裝入、或者從歸檔文件中提取、或者實時編譯。無論是哪一種,那是種特殊的神奇方式,使我們獲得了原始類文件字節(jié)。)
1.??
調(diào)用
findLoadedClass
來查看是否存在已裝入的類。
2.??
如果沒有,那么采用那種特殊的神奇方式來獲取原始字節(jié)。
3.??
如果已有原始字節(jié),調(diào)用
defineClass
將它們轉(zhuǎn)換成
Class
對象。
4.??
如果沒有原始字節(jié),然后調(diào)用
findSystemClass
查看是否從本地文件系統(tǒng)獲取類。
5.??
如果
resolve
參數(shù)是
true
,那么調(diào)用
resolveClass
解析
Class
對象。
6.??
如果還沒有類,返回
ClassNotFoundException
。
7.??
否則,將類返回給調(diào)用程序。
第二種選擇
:
當(dāng)前上下文環(huán)境下的類加載器
.