JVM在加載類時默認(rèn)采用的是雙親委派機(jī)制。
某個特定的類加載器在接到加載類的請求時,首先將加載任務(wù)委托給父類加載器,依次遞歸 (本質(zhì)上就是loadClass函數(shù)的遞歸調(diào)用)。因此,所有的加載請求最終都應(yīng)該傳送到頂層的啟動類加載器中。如果父類加載器可以完成這個類加載請求,就成功返回;只有當(dāng)父類加載器無法完成此加載請求時,子加載器才會嘗試自己去加載。事實(shí)上,大多數(shù)情況下,越基礎(chǔ)的類由越上層的加載器進(jìn)行加載,因?yàn)檫@些基礎(chǔ)類之所以稱為“基礎(chǔ)”,是因?yàn)樗鼈兛偸亲鳛楸挥脩舸a調(diào)用的API(當(dāng)然,也存在基礎(chǔ)類回調(diào)用戶用戶代碼的情形)。
雙親委派的具體實(shí)現(xiàn)就在抽象類java.lang.ClassLoader的loadClass方法中,以下是ClassLoader幾個核心方法。load會先查父加載器的load方法加載類,如果無法加載,就會調(diào)用find方法尋找類定義字節(jié)碼,以便加載,如果找到了,就會調(diào)用define方法進(jìn)行加載類。
所以用戶自定義類加載器,只要重寫find方法就可以了。
/加載指定名稱(包括包名)的二進(jìn)制類型,供用戶調(diào)用的接口?
?public Class<?> loadClass(String name) throws ClassNotFoundException{ … }?
//加載指定名稱(包括包名)的二進(jìn)制類型,同時指定是否解析(但是這里的resolve參數(shù)不一定真正能達(dá)到解析的效果),供繼承用?
?protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{ … }
?//findClass方法一般被loadClass方法調(diào)用去加載指定名稱類,供繼承用?
?protected Class<?> findClass(String name) throws ClassNotFoundException { … } ?
//定義類型,一般在findClass方法中讀取到對應(yīng)字節(jié)碼后調(diào)用,final的,不能被繼承 //這也從側(cè)面說明:JVM已經(jīng)實(shí)現(xiàn)了對應(yīng)的具體功能,解析對應(yīng)的字節(jié)碼,產(chǎn)生對應(yīng)的內(nèi)部數(shù)據(jù)結(jié)構(gòu)放置到方法區(qū),所以無需覆寫,直接調(diào)用就可以了)?
?protected final Class<?> defineClass(String name, byte[] b, int off, int len) throws ClassFormatError{ … }