其他文章
【Java】深入理解Java虛擬機1——內(nèi)存區(qū)域以及OOM類型:http://www.reibang.com/p/65c91ba4006e
【Java】深入理解Java虛擬機2——判斷對象是否存活和引用:http://www.reibang.com/p/67c24aa93c03
【Java】深入理解Java虛擬機3——垃圾收集算法:http://www.reibang.com/p/362407886236
【Java】深入理解Java虛擬機4——內(nèi)存分配與回收策略:http://www.reibang.com/p/e21f5d5c4f42
【Java】深入理解Java虛擬機5——類的加載過程:http://www.reibang.com/p/931ef115d48e
【Java】深入理解Java虛擬機6——類的加載器及雙親委派:http://www.reibang.com/p/2f33eca93a4f
類的加載器
對于任意一個類,都需要由加載它的類加載器和這個類本身一同確立其在Java虛擬機中的唯一性变屁,每一個類加載器,都擁有一個獨立的類名稱空間慎颗。
注:比較兩個類是否“相等”,只有在這兩個類是由同一個類加載器加載的前提下才有意義,否則俯萎,即使這兩個類來源于同一個Class文件傲宜,被同一個虛擬機加載,只要加載它們的類加載器不同夫啊,那這兩個類就必定不相等函卒。這里所指的“相等”,包括代表類的Class對象的equals()方法撇眯、isAssignableFrom()方法报嵌、isInstance()方法的返回結(jié)果,也包括使用instanceof關(guān)鍵字做對象所屬關(guān)系判定等情況叛本。
/**
* 類加載器與instanceof關(guān)鍵字演示
*
* @author zzm
*/
public class ClassLoaderTest {
public static void main(String[] args)throws Exception {
ClassLoader myLoader = new ClassLoader(){
@Override
public Class<?>loadClass(String name)throws ClassNotFoundException {
try {
String fileName = name.substring(name.lastIndexOf(".")+1)+".class";
InputStream is = getClass().getResourceAsStream(fileName)彤钟;
if(is == null){
return super.loadClass(name)来候;
}
byte[] b = new byte[is.available()];
is.read(b)逸雹;
return defineClass(name, b营搅,0,b.length)梆砸;
} catch(IOException e){
throw new ClassNotFoundException(name)转质;
}
}
};
Object obj = myLoader.loadClass("org.fenixsoft.classloading.ClassLoaderTest").
newInstance()帖世;
System.out.println(obj.getClass())休蟹;
System.out.println(obj instanceof org.fenixsoft.classloading.ClassLoaderTest);
}
}
運行結(jié)果:
class org.fenixsoft.classloading.ClassLoaderTest
false
根據(jù)結(jié)果分析日矫,這個對象確實是類org.fenixsoft.classloading.ClassLoaderTest實例化出來的對象赂弓,但是返回結(jié)果為false,是因為虛擬機中存在了兩個ClassLoaderTest類哪轿,一個是由系統(tǒng)應(yīng)用程序類加載器加載的盈魁,另外一個是由我們自定義的類加載器加載的,雖然都來自同一個Class文件窃诉,但依然是兩個獨立的類杨耙,做對象所屬類型檢查時結(jié)果自然為false。
雙親委派模型
從Java虛擬機的角度來講飘痛,只存在兩種不同的類加載器:一種是啟動類加載器(Bootstrap ClassLoader)珊膜,這個類加載器使用C++語言實現(xiàn)[1],是虛擬機自身的一部分宣脉;另一種就是所有其他的類加載器辅搬,這些類加載器都由Java語言實現(xiàn),獨立于虛擬機外部,并且全都繼承自抽象類java.lang.ClassLoader堪遂。
啟動類加載器(Bootstrap ClassLoader)
負責(zé)將存放在<JAVA_HOME>\lib目錄中的介蛉,或者被-Xbootclasspath參數(shù)所指定的路徑中的,并且是虛擬機識別的(僅按照文件名識別溶褪,如rt.jar币旧,名字不符合的類庫即使放在lib目錄中也不會被加載)類庫加載到虛擬機內(nèi)存中。啟動類加載器無法被Java程序直接引用猿妈,用戶在編寫自定義類加載器時吹菱,如果需要把加載請求委派給引導(dǎo)類加載器,那直接使用null代替即可彭则,如下:
/**
Returns the class loader for the class.Some implementations may use null to
represent the bootstrap class loader.This method will return null in such
implementations if this class was loaded by the bootstrap class loader.
*/
public ClassLoader getClassLoader(){
ClassLoader cl = getClassLoader0 ();
if (cl == null)
return null;
SecurityManager sm = System . getSecurityManager ();
if (sm鳍刷! = null){
ClassLoader ccl = ClassLoader . getCallerClassLoader ();
if (ccl! = null&&ccl俯抖! = cl&&输瓜!cl.isAncestor(ccl)){
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
return cl;
}
擴展類加載器(Extension ClassLoader)
這個加載器由sun.misc.Launcher$ExtClassLoader實現(xiàn),它負責(zé)加載<JAVA_HOME>\lib\ext目錄中的芬萍,或者被java.ext.dirs系統(tǒng)變量所指定的路徑中的所有類庫尤揣,開發(fā)者可以直接使用擴展類加載器。
應(yīng)用程序類加載器(Application ClassLoader)
這個類加載器由sun.misc.Launcher $AppClassLoader實現(xiàn)柬祠。這個類加載器是ClassLoader的getSystemClassLoader()方法的返回值北戏,所以一般也稱它為系統(tǒng)類加載器。它負責(zé)加載用戶類路徑(ClassPath)上所指定的類庫漫蛔,開發(fā)者可以直接使用這個類加載器嗜愈,如果應(yīng)用程序中沒有自定義過自己的類加載器,一般情況下這個就是程序中默認的類加載器莽龟。
雙親委派模型(Parents Delegation Model)
雙親委派模型要求除了頂層的啟動類加載器外芝硬,其余的類加載器都應(yīng)當(dāng)有自己的父類加載器。這里類加載器之間的父子關(guān)系一般不會以繼承(Inheritance)的關(guān)系來實現(xiàn)轧房,而是都使用組合(Composition)關(guān)系來復(fù)用父加載器的代碼拌阴。
注:它并不是一個強制性的約束模型,而是Java設(shè)計者推薦給開發(fā)者的一種類加載器實現(xiàn)方式奶镶。
雙親委派模型的工作過程是:如果一個類加載器收到了類加載的請求迟赃,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成厂镇,每一個層次的類加載器都是如此纤壁,因此所有的加載請求最終都應(yīng)該傳送到頂層的啟動類加載器中,只有當(dāng)父加載器反饋自己無法完成這個加載請求(它的搜索范圍中沒有找到所需的類)時捺信,子加載器才會嘗試自己去加載酌媒。
注:使用雙親委派模型來組織類加載器之間的關(guān)系欠痴,有一個顯而易見的好處就是Java類隨著它的類加載器一起具備了一種帶有優(yōu)先級的層次關(guān)系。例如類java.lang.Object秒咨,它存放在rt.jar之中喇辽,無論哪一個類加載器要加載這個類,最終都是委派給處于模型最頂端的啟動類加載器進行加載雨席,因此Object類在程序的各種類加載器環(huán)境中都是同一個類菩咨。相反,如果沒有使用雙親委派模型陡厘,由各個類加載器自行去加載的話抽米,如果用戶自己編寫了一個稱為java.lang.Object的類,并放在程序的ClassPath中糙置,那系統(tǒng)中將會出現(xiàn)多個不同的Object類云茸,Java類型體系中最基礎(chǔ)的行為也就無法保證,應(yīng)用程序也將會變得一片混亂谤饭。
錯誤不足之處或相關(guān)建議歡迎大家評論指出标捺,謝謝!如果覺得內(nèi)容可以的話麻煩喜歡(?)一下网持。您的支持是我最大的動力宜岛。