java 类加载器加载顺序 经典例子
? 寫了一個(gè)string 類,和api中包名,類名都是一樣的,然后去加載:?
1 package java.lang; 2 public class String{ 3 public static void main(String[] args ){ 4 } 5 }?大家發(fā)現(xiàn)什么不同了嗎?對(duì)了,我們寫了一個(gè)與JDK中String一模一樣的類,連包java.lang都一樣,唯一不同的是我們自定義的String類有一個(gè)main函數(shù)。我們來運(yùn)行一下:
?java.lang.NoSuchMethodError: main
?Exception in thread "main"
這是為什么? 我們的String類不是明明有main方法嗎?
其實(shí)聯(lián)系到j(luò)vm類加載的雙親委托模型,我們就能解釋這個(gè)問題了。
????? 運(yùn)行這段代碼,AppClassLoader會(huì)嘗試加載java.lang.String這個(gè)類,但是根據(jù)雙親委托模型AppClassLoader會(huì)將加載java.lang.String的請(qǐng)求委托給ExtClassLoader,而 ExtClassLoader又會(huì)委托給最后的啟動(dòng)類加載器BootstrapLoader。
????? 啟動(dòng)類加載器BootstrapLoader只能加載JAVA_HOME\jre\lib中的class類(即J2SE API),問題是標(biāo)準(zhǔn)API中確實(shí)有一個(gè)java.lang.String(注意,這個(gè)類和我們自定義的類是完全兩個(gè)類)。BootstrapLoader以為找到了這個(gè)類,毫不猶豫的加載了j2se api中的java.lang.String。
????? 最后出現(xiàn)上面的加載錯(cuò)誤(注意不是異常,是錯(cuò)誤,JVM退出),因?yàn)锳PI中的String類是沒有main方法的。
結(jié)論:我們當(dāng)然可以自定義一個(gè)和API完全一樣的類,但是由于雙親委托模型,使得我們不可能加載上我們自定義的這樣一個(gè)類。所以J2SE規(guī)范中希望我們自定義的包有自己唯一的特色(網(wǎng)絡(luò)域名)。還有一點(diǎn),這種加載器原理使得JVM更加安全的運(yùn)行程序,因?yàn)楹诳秃茈y隨意的替代掉API中的代碼了。
Java虛擬機(jī)中可以安裝多個(gè)類加載器,系統(tǒng)默認(rèn)三個(gè)主要類加載器,每個(gè)類負(fù)責(zé)加載特定位置的類:BootStrap,ExtClassLoader,AppClassLoader 類加載器也是Java類,因?yàn)槠渌莏ava類的類加載器本身也要被類加載器加載,顯然必須有第一個(gè)類加載器不是不是java類,這正是BootStrap。
jvm三級(jí)類加載器 類加載采用委托模型,就是頂層類加載器先是啟動(dòng),然后將加載類動(dòng)作傳給(委托)上一層父類加載器,依次到bootstrap classloader,當(dāng)根加載器沒有加載到,那么又會(huì)返回給其下一級(jí)子類加載器,依次又傳給當(dāng)前的子類加載器。如果還沒有找到,那么就是class not found.說白了無論加載什么類,都是從根加載起來的,根類庫(kù)沒有依次往后找。 為什么要有這種委托機(jī)制? 這樣的好處,不讓你修改Java原生的類庫(kù)和本地類庫(kù),如果你想自己定義,可以應(yīng)該是修改了包名或者類名,這樣也能防止網(wǎng)絡(luò)傳過來的類取代本地類庫(kù)或者api,防止入侵。
總結(jié)
以上是生活随笔為你收集整理的java 类加载器加载顺序 经典例子的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【参考文献管理工具-1】使用Mendel
- 下一篇: spring bean依赖与配置