一、ClassLoader 源码doc文档
ClassLoader是一个负责加载类的对象,它本身是一个抽象类。在给定一个类的二进制名字时,类加载器会尝试去定位(已经存在的class文件)或生成(动态代理生成的类)构成类定义的数据。一种典型的策略是将给定的二进制的类名转换成文件名,然后从文件系统中读取该类对应的class文件。
每一个类对象都会包含加载该类的类加载器的引用。
数组的class对象并不是由类加载器创建的,而是在java运行时,根据需要自动创建的。而对于数组类型的类加载器来说,通过调用class.getClassLoader()方法返回的类加载器,与数组元素的类加载器是相同的。如果数组的元素是一个原生类型,那么数组的类加载器为null。
实现ClassLoader类的子类的应用,是为了扩展实现Java虚拟机动态加载类的一种方式。
通常情况下,类加载器会被安全管理器来表示一些安全与的问题。
类加载器使用了一种委托机制来寻找类或者资源。类加载器的每一个实例,都会有一个与之相关的父类加载器。当类加载器被要求寻找类或者资源的时候,类加载器会在自己尝试去加载之前,将该请求委托给他的父类加载器。虚拟机内置的类加载器,称之为启动类加载器,她本身是没有父类加载器的,但它可以作为其它类加载器的父类加载。
支持并发加载类的类加载器叫做并发类加载器,并且它被要求在类的初始化阶段,通过调用class.registerAsParallelCapable()方法来完成对自身的注册。需要注意的是,在默认情况下,类加载器是会被注册为并发类加载器的。然而,他的子类如果也是并发类加载器的话,仍需要自己注册的。
在委托机制并不是严格层次化的环境下,类加载器是需要做到并发的,否则的话,类加载就会变成死锁。因为在类加载期间,加载类的锁会被一直持有。
通常情况下,java虚拟机会以一种与平台相关的形式,从本地文件系统中加载类。如在unix系统中,虚拟机会从classpath环境变量所定义的目录中加载类。然而有些class文件名并不是来源于某个文件,他们可能来源于其他,如网络或者是由应用程序本身所创建的,而defineClass()会将字节数组转化为一个Class类对象的实例。新定义的类的实例,可以通过class.newInstance()来完成创建。
由类加载器创建的方法或者构造方法中还可能会引用其他的类。为了确定类的引用,java虚拟机会调用创建该类的类加载器的loadclass方法。
二、数组类加载器的测试代码
public class TestCode15 {public static void main(String[] args) {String[] ary1 = new String[2];// null,启动类加载器加载StringSystem.out.println(ary1.getClass().getClassLoader());System.out.println("--------");TestCode15[] ary2 = new TestCode15[3];// AppClassLoader 系统类加载器System.out.println(ary2.getClass().getClassLoader());System.out.println("--------");int[] ary3 = new int[2];// null,原生类型类加载器返回 nullSystem.out.println(ary3.getClass().getClassLoader());}
}
执行结果:
null
--------
sun.misc.Launcher$AppClassLoader@6fefa3e7
--------
null