在程序运行期间, 经过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