java classloader 過程

jvm classLoader architecture :
a, Bootstrap ClassLoader/啓動類加載器
主要負責jdk_home/lib目錄下的核心 api 或 -Xbootclasspath 選項指定的jar包裝入工做.
 
b, Extension ClassLoader/擴展類加載器
主要負責jdk_home/lib/ext目錄下的jar包或 -Djava.ext.dirs 指定目錄下的jar包裝入工做
 
c, System ClassLoader/系統類加載器 (AppClassLoader ?)
主要負責java -classpath/-Djava.class.path所指的目錄下的類與jar包裝入工做.
 
b, User Custom ClassLoader/用戶自定義類加載器(java.lang.ClassLoader的子類)

在程序運行期間, 經過java.lang.ClassLoader的子類動態加載class文件, 體現java動態實時類裝入特性. java

類加載器的特性:
1, 每一個ClassLoader都維護了一份本身的名稱空間, 同一個名稱空間裏不能出現兩個同名的類。
2, 爲了實現java安全沙箱模型頂層的類加載器安全機制, java默認採用了 」 雙親委派的加載鏈 」 結構.


以下圖:
api

java class loader

類圖: 安全

classloader 類圖

類圖中, BootstrapClassLoader是一個單獨的java類, 其實在這裏, 不該該叫他是一個java類(C++)。
由於, 它已經徹底不用java實現了。
 
它是在jvm啓動時, 就被構造起來的, 負責java平臺核心庫。(具體上面已經有介紹) jvm

自定義類加載器加載一個類的步驟 : spa

自定義類加載器加載一個類的步驟

ClassLoader 類加載邏輯分析, 如下邏輯是除 BootstrapClassLoader 外的類加載器加載流程: code

// 檢查類是否已被裝載過
Class c = findLoadedClass(name);
if (c == null ) {
     // 指定類未被裝載過
     try {
         if (parent != null ) {
             // 若是父類加載器不爲空, 則委派給父類加載
             c = parent.loadClass(name, false );
         } else {
             // 若是父類加載器爲空, 則委派給啓動類加載加載
             c = findBootstrapClass0(name);
         }
     } catch (ClassNotFoundException e) {
         // 啓動類加載器或父類加載器拋出異常後, 當前類加載器將其
         // 捕獲, 並經過findClass方法, 由自身加載
         c = findClass(name);
     }
}

若是父加載器加載不到,就由本身加載,因此若是本身定義一個類加載器,通常重寫一個findClass方法,見下面代碼 對象

protected Class findClass( String pClassName )

           throws ClassNotFoundException {

       try {

           System.out.println( "Current dir: " + new File( mDirectory ).getAbsolutePath() );

           File lClassFile = new File( mDirectory, pClassName + ".class" );

           InputStream lInput = new BufferedInputStream( new FileInputStream( lClassFile ) );

           ByteArrayOutputStream lOutput = new ByteArrayOutputStream();

           int i = 0;

           while( ( i = lInput.read() ) >= 0 ) {

               lOutput.write( i );

           }

           byte[] lBytes = lOutput.toByteArray();

           return defineClass( pClassName, lBytes, 0, lBytes.length );

       } catch( Exception e ) {

           throw new ClassNotFoundException( "Class: " + pClassName + " could not be found" );

       }

   }



findClass方法主要的工做是在指定路徑中查找咱們須要的類。若是存在此命名的類,那麼就將class文件加載到jvm中,再由defineClass方法(一個native方法)來生成具體的Class對象。 ssl

用Class.forName加載類
Class.forName使用的是被調用者的類加載器來加載類的.
這種特性, 證實了java類加載器中的名稱空間是惟一的, 不會相互干擾.
即在通常狀況下, 保證同一個類中所關聯的其餘類都是由當前類的類加載器所加載的.
public static Class forName(String className)
     throws ClassNotFoundException {
     return forName0(className, true , ClassLoader.getCallerClassLoader());
}
 
/** Called after security checks have been made. */
private static native Class forName0(String name, boolean initialize,
ClassLoader loader)
     throws ClassNotFoundException;

上圖中 ClassLoader.getCallerClassLoader 就是獲得調用當前forName方法的類的類加載器 get

相關文章
相關標籤/搜索