javadoc的解释:
ClassLoader的每一个实例都会有一个与之关联的父ClassLoader,当被要求去寻找一个类或者资源的时候,ClassLoader的实例就会对于类或者是资源的寻找委托给他的父ClassLoader(在他自己尝试找这个类或者资源之前),并层层向上委托。
虚拟机内建的ClassLoader即Bootstrap根类加载器,他本身是没有双亲的,但是他可以作为一个类加载器的双亲。
支持并发加载类的类加载器,被称为 parallel capable class loaders ,被要求在类的初始化期间调用ClassLoader.registerAsParallelCapable()将自身注册为parallelcapableclassloader。 ClassLoader默认是并发类加载器,但他的子类如果是并发的,还依然需要注册。
当境委派模型并不是严格的层次委派模型时,要求类加载器必须是支持并行的类加载器,否则类加载就会导致死锁。因为加载器的锁(loader lock我也不知道咋翻译)在类的加载过程中一直不会释放。
一般来说jvm虚拟机加载类来源于本地文件系统(与操作系统跟平台相关),但也可能来源于其他资源,比如网络,或者运行时的动态生成。
在这种情况下,加载类的方法会把一个字节数组(调用 loadClassData() 返回byte[] ,通过defineClass(byte[])转为一个Class)转换为一个class对象,通过Class.newInstance 来创建对应对象。
class NetworkClassLoader extends ClassLoader { public Class findClass(String name) { private byte[] loadClassData(String name) { } |
由类加载器创建的对象,其方法或者构造器可能引用了其他未加载的类,为了确定这些引用是什么(注意这些引用对应的类还未被装入,需要确定这些引用是什么) jvm虚拟机会调用加载这个类的class的classloader 来加载这些引用(再次跳入第一步 开始递归)
1.获取ClassLoader
1 public class MyTest06 { 2 3 public static void main(String[] args) { 4 String str = new String("212"); 5 C c = new C(); 6 System.out.println(str.getClass().getClassLoader()); 7 System.out.println(c.getClass().getClassLoader()); 8 } 9 10 } 11 class C{ 12 13 }//out: null
sun.misc.Launcher$AppClassLoader@2a139a55
第二个返回值说明自定义类C是由AppClassLoader 系统类加载器加载
第一个返回值说明String由Bootstrap根加载器加载
/** 如下是源码中对 getClassLoader() 方法的说明* Returns the class loader for the class. Some implementations may use* null to represent the bootstrap class loader. This method will return* null in such implementations if this class was loaded by the bootstrap* class loader.* 如果类由bootstrap class loader加载 这个方法会返回null在一些jvm实现中* * <p> If a security manager is present, and the caller's class loader is* not null and the caller's class loader is not the same as or an ancestor of* the class loader for the class whose class loader is requested, then* this method calls the security manager's {@code checkPermission}* method with a {@code RuntimePermission("getClassLoader")}* permission to ensure it's ok to access the class loader for the class.** <p>If this object* represents a primitive type or void, null is returned.** @return the class loader that loaded the class or interface* represented by this object.* @throws SecurityException* if a security manager exists and its* {@code checkPermission} method denies* access to the class loader for the class.* @see java.lang.ClassLoader* @see SecurityManager#checkPermission* @see java.lang.RuntimePermission*/
2.ClassLoader.loadClass()方法与Class.forName()方法
class CL{static {System.out.println("class cl");}
}
public class MyTest07 {public static void main(String[] args) throws Exception {ClassLoader clazzloader = ClassLoader.getSystemClassLoader();Class<?> clazz = clazzloader.loadClass("jvm.CL");System.out.println("==================================");System.out.println(clazz);System.out.println("==================================");Class<?> clazz2 = Class.forName("jvm.CL");System.out.println("==================================");System.out.println(clazz2);}}//out:
==================================
class jvm.CL
==================================
class cl
==================================
class jvm.CL
loadclass 只加载对应类,forName 会一并将类初始化
不过调用 clazz.newInstance()会初始化该类:
public class MyTest07 {public static void main(String[] args) throws Exception {ClassLoader clazzloader = ClassLoader.getSystemClassLoader();Class<?> clazz = clazzloader.loadClass("jvm.CL");System.out.println("==================================");System.out.println(clazz);System.out.println("==================================");clazz.newInstance();System.out.println("==================================");Class<?> clazz2 = Class.forName("jvm.CL");System.out.println("==================================");System.out.println(clazz2);}}out:
==================================
class jvm.CL
==================================
class cl
==================================
==================================
class jvm.CL
3.HotSpot实现中用null代替根加载器Bootstrap
public class MyTest08 {public static void main(String[] args) {ClassLoader classloader = ClassLoader.getSystemClassLoader();System.out.println(classloader);while(classloader!=null) {classloader= classloader.getParent();System.out.println(classloader);}}}//out:
sun.misc.Launcher$AppClassLoader@2a139a55
sun.misc.Launcher$ExtClassLoader@7852e922
null
4.数组的classloader,数组是JVM在运行时动态生成的类型,没有类加载器,如果调用getClassLoader会返回对应元素的类加载器。
public class MyTest09 {public static void main(String[] args) {String[] strs = new String[2];System.out.println(strs.getClass().getClassLoader());System.out.println("============================");MyTest09[] ms = new MyTest09[2];System.out.println(ms.getClass().getClassLoader());System.out.println("============================");int[] ints = new int[2];System.out.println(ints.getClass().getClassLoader());}}//out:
null
============================
sun.misc.Launcher$AppClassLoader@2a139a55
============================
null
其中String类型的类加载器是Bootstrap 在HotSpot实现中被表现为null
源生类型则没有类加载器。
5.类加载器一般都会伴随一个安全管理器,来确保类加载过程中是安全的