在程序運行期間, 經過java.lang.ClassLoader的子類動態加載class文件, 體現java動態實時類裝入特性. java
類加載器的特性:
1, 每一個ClassLoader都維護了一份本身的名稱空間, 同一個名稱空間裏不能出現兩個同名的類。
2, 爲了實現java安全沙箱模型頂層的類加載器安全機制, java默認採用了 」 雙親委派的加載鏈 」 結構.
以下圖:
api
類圖: 安全
類圖中, 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加載類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