尋找類字節碼文件並構造出類在JVM內部表示的組件.負責運行時查找和裝入Class字節碼文件java
查找裝載class字節碼文件數組
執行校驗,準備和解析步驟,其中解析步驟時可選的緩存
檢查裝載Class文件的正確性安全
給類的靜態變量分配存儲空間網絡
將符號引用轉換爲直接引用app
對類的靜態變量,方法,代碼塊執行初始化操做jvm
最頂層的裝載器,它不是ClassLoader的子類,採用C++編寫,所以在JAVA中不可見。主要負責裝載JRE核心類庫。能夠經過jvm啓動參數-Xbootclasspath改變該加載器加載的路徑函數
主要負責加載JRE擴展目錄ext下的包,能夠經過-D java.ext.dirs選項指定目錄源碼分析
負責加載當前工程目錄下,classpath下的包或者class文件post
其中Extention ClassLoader & AppClassLoader是ClassLoader的子類,根加載器是擴展加載器的父加載器,擴展加載器是應用加載器的父加載器。在默認狀況下使用應用加載器
類加載採用「全盤負責委託機制」。
「全盤負責」:在類加載時指定一個ClassLoader,除非顯示聲明其餘的加載器,不然該類所依賴的類以及引用的類都由該加載器加載。
「委託機制」:類加載時優先委託父加載器尋找並加載目標類,只有在父加載器沒有找到的狀況下,才從本身的classpath路徑下查找並加載目標類。該點主要是出於安全的考慮,在classpath路徑下定義JDK中已經存在的類,因爲該機制,JDK中的類都由父加載器開始查找並加載.每一個加載器都有緩存,在委託時優先查找緩存,若是緩存中存在,那麼直接返回,否者才執行查找和加載
類文件被加載後,在JVM內部對應擁有一個java.lang.Class類描述對象,類的每一個實例擁有類描述對象的引用,類描述對象擁有類加載器的引用
Bootstrap ClassLoader-->Extention ClassLoader-->AppClass Loader即Bootstrap ClassLoader最早啓動,接着是Extenion ClassLoader,最後是AppClass Loader
1.定義Bootstrap ClassLoader加載路徑(sun.boot.class.path)
2.建立Extention ClassCloader
3.建立App ClassLoader並設置App ClassLoader的父類:Extention ClassCloader
該類中定義了Bootstrap ClassLoader加載路徑,同時建立了Extention ClassLoader以及AppClassLoader,以下是Bootstrap ClassLoader加載路徑信息
從輸出路徑上看Bootstrap ClassLoader主要加載的是jre/lib目錄下的資源.即JVM Runtime核心庫
1.根據查找路徑得到路徑(jav.ext.dirs)下文件
2.將文件路徑轉換爲URL
3.調用父類構造函數,建立ExtClassLoader並設置父加載器
以下是java.ext.dirs的輸出信息
1.得到java.classs.path路徑下的全部文件
2.解析文件路徑爲URL
3.調用父類構造函數建立AppClassLoader並設置父類
Java.class.path輸出信息
/work/new_workspace/aaa/bin
java.lang.Object
java.lang.ClassLoader
java.security.SecureClassLoader
java.net.URLClassLoader
ExtClassLoader
AppClassLoader
能夠經過getParent()得到當前加載器的父加載器
爲何得到ExtClassLoader的父加載器爲null?這和每一個加載器都有一個父加載器違背.這個屬於正常現象.具體緣由以下:
1.從ExtClassLoader構造函數super(getExtURLs(dirs), null, factory);能夠看出此時傳入的就是null
2.Bootstrap ClassLoader是由C/C++編寫的,它自己是虛擬機的一部分,不是一個JAVA類,沒法在java代碼中獲取它的引用,凡是sun.boot.class.path路徑下的包以及類都是由它加載。JVM初始化sun.misc.Launcher建立Extension ClassLoader和AppClassLoader實例。並將ExtClassLoader設置爲AppClassLoader的父加載器。BootstrapClassCloader沒有父加載器,可是它卻能夠做爲一個ClassLoader的父加載器。好比ExtClassLoader。這也能夠解釋以前經過ExtClassLoader的getParent方法獲取爲Null的現象.咱們能夠分析getParent()的源碼
父加載器能夠直接由外界指定,若是外界不指定,那麼採用AppClassLoader做爲父加載器
//在建立ExtClassLoader時,採用super(getExtURLs(dirs), null, factory).因此得到的是null
查找給定名稱的資源。資源的名稱是一個/分隔的路徑名稱標識資源,優先查找父加載器,若是找不到在從Bootstrap ClassLoader路徑中查找並加載
查找給定名稱的全部資源。資源的名稱是一個/分隔的路徑名稱標識資源,優先查找父加載器,若是找不到在從Bootstrap ClassLoader路徑中查找並加載,該模式下支持正則匹配
採用AppClassLoader加載給定名稱的資源
採用AppClassLoader加載給定名稱的全部資源
查找具備給定名稱的資源。類加載器實現應覆蓋此方法以指定在哪裏查找資源
查找具備給定名稱的全部資源。類加載器實現應覆蓋此方法以指定在哪裏查找資源
loadClass(String name) & loadClass(String name, boolean resolve)name指定了類裝載器的名字,必須使用全限定名。resolve告訴裝載器是否須要解析該類。在初始化以前,應該考慮進行類解析工做。並非全部的類都須要解析的。若是JVM只須要知道該類是否存在或者找出該類的超類,那麼就不須要解析該類
將類文件字節碼數組裝換成JVM內部的java.lang.Class對象,字節數組能夠從本地系統,遠程網絡獲取
從本地文件系統載入Class文件,若是本地文件系統中不存在該Class文件,拋出ClassNotFoundError。該方法是JVM默認使用的裝載器
該方法查看ClassLoader是否已經加載了某個類,若是載入就返回Class對象,不然返回null,若是強行載入已經載入的類會拋出異常
1.編寫一個類繼承ClassLoader
2.重寫findClass 方法
3.在findClass中調用defineClass便可
contextClassLoader只是一個成員變量,經過setContextClassLoader()方法設置,經過getContextClassLoader()得到。
每一個Thread都有一個相關聯的ClassLoader,默認是AppClassLoader。而且子線程默認使用父線程的ClassLoader除非子線程特別設置
常見的用法是將Class文件按照某種加密手段進行加密,而後按照規則編寫自定義的ClassLoader進行解密,這樣咱們就能夠在程序中加載特定了類,而且這個類只能被咱們自定義的加載器進行加載,提升了程序的安全性。