ClassLoader

類從加載到虛擬機內存開始,到卸載出內存,它的整個生命週期包括:加載(loading)、驗證(verification)、準備(preparation)、解析(resolution)、初始化(initialization)、使用(using)、卸載(unloading)7個階段。其中驗證、準備、解析3個部分統稱爲鏈接(linking)java

 

JVM規範規定有且僅有下面5種狀況會觸發類的初始化(加載、驗證、準備在這以前完成):spa

  1. 遇到new、getstatic、putstatic、invokestatic這4個字節碼命令時,若是累沒有進行過初始化,則須要先觸發其初始化。這4條命令對應的場景:使用new關鍵字實例化對象、讀取或設置一個類的靜態變量(被final修飾、已在編譯期把結果放入常量池的除外),以及調用靜態方法的時候。
  2. 使用java.lang.reflect包的方法對類進行反射調用的時候,若是類沒有加載過
  3. 當初始化一個類當其父類沒有初始化過,則先初始化父類
  4. 當虛擬機啓動,會先初始化main方法主類
  5. 當使用JDK 7的動態語言支持時,若是一個java.lang.invoke.MethodHandle實例最後解析結果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,而且這個方法句柄所對應的類沒有進行過初始化,則須要先觸發其初始化

 

接口的初始化與類初始化相似,只有3.不一樣,父類接口只在用到時候纔會初始化設計

 

 

ClassLoader類加載器,主要的做用對象

  1. 負責將Class加載到JVM中;
  2. 審查每一個類應該由誰加載;
  3. 將Class字節碼從新解析成JVM統一要求的對象格式;

 

ClassLoader的幾個主要方法:繼承

  1. defineClass(byte[], int, int)用來將byte字節流解析成JVM可以識別的Class對象
  2. resolveClass(Class<?>)用來鏈接(Link)類
  3. findClass(String)用來實現類的加載規則,從而取得加載類的字節碼。而後能夠結合defineClass方法生成類的Class對象,若是想在類被加載到JVM中時就被鏈接,能夠接着調用resolve方法。
  4. loadClass(String)中會調用findClass方法,默認不調用resolve方法,能夠同太重載方法loadClass(String,boolean)在類加載到JVM是被連接,否則將在對象真正實力化時才進行連接

 

ClassLoader是一個抽象類,它有不少子類,咱們若是要實現本身的ClassLoader,通常都會繼承URLClassLoader這個子類,由於這個類已經幫咱們實現了大部分工做。接口

 

整個JVM中提供了三個ClassLoader類,這三個ClassLoader能夠分爲兩種類型,加載JVM自身工做須要類的加載器和爲其餘類服務的加載器:生命週期

  1. Bootstrap ClassLoader,這個ClassLoader主要加載JVM自身工做須要的類,這個ClassLoader徹底是JVM本身控制,因此不遵照雙親委託接待(Parents Delegation Model)規則。將%JAVA_HOME%\lib路徑下或-Xbootclasspath參數指定路徑下的、能被虛擬機識別的類庫(僅按照文件名識別,如:rt.jar,名字不符合的類庫不會被加載)加載至虛擬機內存中
  2. ExtClassLoader,用來加載System.getProperty("java.ext.dirs")目錄下的類,(默認值是%JAVA_HOME%\jre\lib\ext,可由VM參數-Djava.ext.dirs指定)
  3. AppClassLoader,繼承自ExtClassLoader,這個類加載器用來加載System.getProperty("java.class.path")目錄下的類默認值是系統環境變量classpath的值,可由VM參數-Djava.class.path指定),這個目錄就是咱們經常使用的classpath

 

ExtClassLoader和AppClassLoader都位於sun.misc.Launcher類中,都是Launcher類的內部類。內存

 

ClassLoader分爲不一樣的等級,爲了保證每一個類只能在某個級別的ClassLoader被加載一次,ClassLoader設計出了雙親委託接待(Parents Delegation Model),規則以下:get

若是一個類加載器收到了加載類的請求,首先檢查這個類是否已經被當前加載器加載過,若是沒加載過它首先不會本身去嘗試加載這個類,而是把這個請求委託給上級類加載器去完成,每個層次的類加載器都是如此,全部加載器的加載請求最終都應該傳送至最頂層的類加載器中(擴展類加載器),只有當上級類加載器反饋本身沒法完成這個加載請求(它的類加載範圍中沒有找到所需的類)時,下級類加載器纔會去嘗試本身加載這個類,這即是類加載器的雙親委託接待(Parents Delegation Model)虛擬機

 

雙親委託使得類加載器有了優先級順序,保證了全部JVM須要的基礎類如Obejct等都是使用的rt.jar的系統類,防止了用戶自定義的同名類,形成類混亂

相關文章
相關標籤/搜索