jvm:类加载器与双亲委派模型
兩個(gè)類(lèi)相等需要類(lèi)本身相等,并且使用同一個(gè)類(lèi)加載器進(jìn)行加載。這是因?yàn)槊恳粋€(gè)類(lèi)加載器都擁有一個(gè)獨(dú)立的類(lèi)名稱空間。
這里的相等,包括類(lèi)的 Class 對(duì)象的 equals() 方法、isAssignableFrom() 方法、isInstance() 方法的返回結(jié)果為 true,也包括使用 instanceof 關(guān)鍵字做對(duì)象所屬關(guān)系判定結(jié)果為 true。
類(lèi)加載器分類(lèi)
從 Java 虛擬機(jī)的角度來(lái)講,只存在以下兩種不同的類(lèi)加載器:
-
啟動(dòng)類(lèi)加載器(Bootstrap ClassLoader),這個(gè)類(lèi)加載器用 C++ 實(shí)現(xiàn),是虛擬機(jī)自身的一部分;
-
所有其他類(lèi)的加載器,這些類(lèi)由 Java 實(shí)現(xiàn),獨(dú)立于虛擬機(jī)外部,并且全都繼承自抽象類(lèi) java.lang.ClassLoader。
從 Java 開(kāi)發(fā)人員的角度看,類(lèi)加載器可以劃分得更細(xì)致一些:
-
啟動(dòng)類(lèi)加載器(Bootstrap ClassLoader)此類(lèi)加載器負(fù)責(zé)將存放在 <JRE_HOME>\lib 目錄中的,或者被 -Xbootclasspath 參數(shù)所指定的路徑中的,并且是虛擬機(jī)識(shí)別的(僅按照文件名識(shí)別,如 rt.jar,名字不符合的類(lèi)庫(kù)即使放在 lib 目錄中也不會(huì)被加載)類(lèi)庫(kù)加載到虛擬機(jī)內(nèi)存中。啟動(dòng)類(lèi)加載器無(wú)法被 Java 程序直接引用,用戶在編寫(xiě)自定義類(lèi)加載器時(shí),如果需要把加載請(qǐng)求委派給啟動(dòng)類(lèi)加載器,直接使用 null 代替即可。
-
擴(kuò)展類(lèi)加載器(Extension ClassLoader)這個(gè)類(lèi)加載器是由 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)實(shí)現(xiàn)的。它負(fù)責(zé)將 <JAVA_HOME>/lib/ext 或者被 java.ext.dir 系統(tǒng)變量所指定路徑中的所有類(lèi)庫(kù)加載到內(nèi)存中,開(kāi)發(fā)者可以直接使用擴(kuò)展類(lèi)加載器。
-
應(yīng)用程序類(lèi)加載器(Application ClassLoader)這個(gè)類(lèi)加載器是由 AppClassLoader(sun.misc.Launcher$AppClassLoader)實(shí)現(xiàn)的。由于這個(gè)類(lèi)加載器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,因此一般稱為系統(tǒng)類(lèi)加載器。它負(fù)責(zé)加載用戶類(lèi)路徑(ClassPath)上所指定的類(lèi)庫(kù),開(kāi)發(fā)者可以直接使用這個(gè)類(lèi)加載器,如果應(yīng)用程序中沒(méi)有自定義過(guò)自己的類(lèi)加載器,一般情況下這個(gè)就是程序中默認(rèn)的類(lèi)加載器。
雙親委派模型
應(yīng)用程序都是由三種類(lèi)加載器相互配合進(jìn)行加載的,如果有必要,還可以加入自己定義的類(lèi)加載器。
下圖展示的類(lèi)加載器之間的層次關(guān)系,稱為類(lèi)加載器的雙親委派模型(Parents Delegation Model)。該模型要求除了頂層的啟動(dòng)類(lèi)加載器外,其余的類(lèi)加載器都應(yīng)有自己的父類(lèi)加載器。這里類(lèi)加載器之間的父子關(guān)系一般通過(guò)組合(Composition)關(guān)系來(lái)實(shí)現(xiàn),而不是通過(guò)繼承(Inheritance)的關(guān)系實(shí)現(xiàn)。
?
1. 工作過(guò)程
一個(gè)類(lèi)加載器首先將類(lèi)加載請(qǐng)求傳送到父類(lèi)加載器,只有當(dāng)父類(lèi)加載器無(wú)法完成類(lèi)加載請(qǐng)求時(shí)才嘗試加載。
2. 好處
使得 Java 類(lèi)隨著它的類(lèi)加載器一起具有一種帶有優(yōu)先級(jí)的層次關(guān)系,從而使得基礎(chǔ)類(lèi)得到統(tǒng)一。
優(yōu)先級(jí):通過(guò)啟動(dòng)類(lèi)加載器加載的類(lèi) > 擴(kuò)展類(lèi)加載器加載的類(lèi) > 應(yīng)用程序加載器加載的類(lèi)
例如 java.lang.Object 存放在 rt.jar 中,如果編寫(xiě)另外一個(gè) java.lang.Object 的類(lèi)并放到 ClassPath 中,程序可以編譯通過(guò)。由于雙親委派模型的存在,所以在 rt.jar 中的 Object 比在 ClassPath 中的 Object 優(yōu)先級(jí)更高,這是因?yàn)?rt.jar 中的 Object 使用的是啟動(dòng)類(lèi)加載器,而 ClassPath 中的 Object 使用的是應(yīng)用程序類(lèi)加載器。rt.jar 中的 Object 優(yōu)先級(jí)更高,因此在各種類(lèi)加載器環(huán)境中都是同一個(gè)類(lèi)。
每一個(gè)類(lèi),都需要由加載它的類(lèi)加載器和類(lèi)本身來(lái)確定其在JVM中的唯一性?
總結(jié)
以上是生活随笔為你收集整理的jvm:类加载器与双亲委派模型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: JVM:内存分配与回收策略?Full G
- 下一篇: JVM:内存划分总结