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

相关文章
相关标签/搜索