參考:關(guān)于Java類加載雙親委派機(jī)制的思考(附一道面試題)
雙親委派的作用?
防止內(nèi)存中出現(xiàn)多份同樣的字節(jié)碼睛低,Java類隨著加載它的類加載器一起具備了一種帶有優(yōu)先級(jí)的層次關(guān)系案狠。拿Object來(lái)說(shuō),如果不采用雙親委派模型钱雷,那么由各個(gè)類加載器自己取加載的話骂铁,那么系統(tǒng)中會(huì)存在多種不同的Object類。
Bootstrap
類加載器是Bootstrap罩抗,這個(gè)加載器很特殊拉庵,它不是Java類,因此它不需要被別人加載套蒂,它嵌套在Java虛擬機(jī)內(nèi)核里面钞支,也就是JVM啟動(dòng)的時(shí)候Bootstrap就已經(jīng)啟動(dòng)茫蛹,它是用C++寫的二進(jìn)制代碼(不是字節(jié)碼),它可以去加載別的類烁挟。
當(dāng)Java虛擬機(jī)要加載一個(gè)類時(shí)婴洼,到底派出哪個(gè)類加載器去加載呢?
- 首先當(dāng)前線程的類加載器去加載線程中的第一個(gè)類(假設(shè)為類A)撼嗓。
注:當(dāng)前線程的類加載器可以通過(guò)Thread類的getContextClassLoader()獲得柬采,也-可以通過(guò)setContextClassLoader()自己設(shè)置類加載器。 - 如果類A中引用了類B且警,Java虛擬機(jī)將使用加載類A的類加載器去加載類B警没。
- 還可以直接調(diào)用
ClassLoader.loadClass()
方法來(lái)指定某個(gè)類加載器去加載某個(gè)類。
能不能自己寫個(gè)類叫java.lang.System振湾?
答案:通常不可以杀迹,但可以采取另類方法達(dá)到這個(gè)需求。
解釋:為了不讓我們寫System類押搪,類加載采用委托機(jī)制树酪,這樣可以保證爸爸們優(yōu)先,爸爸們能找到的類大州,兒子就沒有機(jī)會(huì)加載续语。而System類是Bootstrap加載器加載的,就算自己重寫厦画,也總是使用Java系統(tǒng)提供的System疮茄,自己寫的System類根本沒有機(jī)會(huì)得到加載。
但是根暑,我們可以自己定義一個(gè)類加載器來(lái)達(dá)到這個(gè)目的力试,為了避免雙親委托機(jī)制,這個(gè)類加載器也必須是特殊的排嫌。由于系統(tǒng)自帶的三個(gè)類加載器都加載特定目錄下的類畸裳,如果我們自己的類加載器放在一個(gè)特殊的目錄,那么系統(tǒng)的加載器就無(wú)法加載淳地,也就是最終還是由我們自己的加載器加載怖糊。