java程序不是本地的可執行程序,它的執行依賴jvm,jvm運行後將 class 文件加載到jvm,而後才能在jvm內部運行。負責加載這些class的組件就是ClassLoader。
JVM自己包含了一個ClassLoader稱爲**BootstrapClassLoader**,和JVM自身同樣,**BootstrapClassLoader**是用本地代碼(c/c++等)實現的,它負責加載核心Java class(如rt.jar裏的class)。另外JVM還提供了兩個ClassLoader,它們都是用Java語言編寫的,由BootstrapClassLoader加載到jvm,它們是**ExtClassLoader**和**AppClassLoader**,其中**ExtClassLoader**負責加載Java擴展 class(如jre/lib/ext下的類),**AppClassLoader**負責加載應用程序自身的類(如-classpath下的class)。java
咱們能夠經過JVM參數 -Xbootclasspath 指定自定義的BootstrapClassLoader,但一般是不須要的。
當運行一個程序的時候,JVM啓動,運行Bootstrap ClassLoader,該ClassLoader加載java核心API(ExtClassLoader和AppClassLoader也在此時被加載),而後調用ExtClassLoader加載擴展API,最後調用AppClassLoader加載應用CLASSPATH下定義的Class,這就是一個程序最基本的加載流程。
JVM自帶的ClassLoader只是懂得從本地文件系統加載標準的java class文件,可是咱們可能會有下面的應用場景:
1)在執行類加載以前,自動驗證數字簽名
2)動態地建立符合用戶特定須要的定製化構建類
3)從特定的場所取得 class,例如數據庫、網絡等
4) 自定義加解密Class 等等
這時候咱們就須要定製本身的ClassLoader,java提供了很方便的api供咱們定製本身的ClassLoader。
事實上當使用Applet的時候,就用到了特定的ClassLoader,由於須要從網絡上加載java class,而且要檢查相關的安全信息。另外,應用服務器大都使用了自定義ClassLoader技術,瞭解類加載原理也有助於咱們更好地開發本身的應用。
##ClassLoader結構
java中內置了不少類加載器,本文只討論幾個核心類加載器:
**ClassLoader**:全部類加載器的基類,它是抽象的,定義了類加載最核心的操做。
**SecureClassLoader**:繼承自ClassLoader,添加了關聯類源碼、關聯繫統policy權限等支持。
**URLClassLoader**:繼承自SecureClassLoader,支持從jar文件和文件夾中獲取class
**ExtClassLoader**:擴展類加載器,繼承自URLClassLoader,負責加載java的擴展類(javax.*等),查看源碼可知其查找範圍爲System.getProperty("java.ext.dirs"),一般是jre/lib/ext
**AppClassLoader**:應用類加載器,繼承自URLClassLoader,也叫系統類加載器(ClassLoader.getSystemClassLoader()可獲得它),它負載加載應用的classpath下的類,查找範圍System.getProperty("java.class.path"),經過-cp或-classpath指定的類都會被其加載
java沒有提供Launcher的源碼,可參考openjdk的Launcher類源碼。c++
上面介紹的是ClassLoader的靜態類結構,在概念上,它們還有樹形結構,java中的每一個ClassLoader都有本身的父加載器(**注意區分,不是類關係上的 super**),能夠經過ClassLoader.getParent() 獲取到,當jvm啓動完成後,默認狀況下,他們的樹形結構是這樣的:
自定義的ClassLoader其父加載器爲AppClassLoader,
AppClassLoader的父加載器爲ExtClassLoader,
ExtClassLoader的父加載器爲null,
null表示其父加載器爲 BootstrapClassLoader(非java實現故顯示爲null)。數據庫
參考:http://blog.csdn.net/conquer0715/article/details/38229203api