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