类加载器负责读取Java字节码,并转换成java.lang.Class类的一个实例。
1. 类加载器的分类
站在虚拟机的角度,类加载器分为两类:一种是启动类加载器(Bootstrap ClassLoader),是虚拟机自身的一部分;另外一种就是独立于虚拟机外部的类加载器,继承自抽象类java.lang.ClassLoader。
站在Java开发人员的角度,可细分为:
启动类加载器(Bootstrap ClassLoader):负责加载lt;JAVA_HOMEgt;\lib目录中的,或者由-Xbootclasspath参数指定的路径中的类库。这些类库根据文件名被虚拟机识别,如rt.jar,名字不符号的类库即使在这些目录中也不会被加载。
扩展类加载器(Extension ClassLoader):负责加载lt;JAVA_HOMEgt;\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库。由sun.misc.Launcher$ExtClassLoader实现。
应用程序类加载器(Application ClassLoader):负责加载环境变量Classpath指定路径中的,或者被java.class.path系统变量所指定的路径中的所有类库。由sun.misc.Launcher$AppClassLoader实现。可以通过ClassLoader.getSystemClassLoader()方法的返回值得到。
用户自定义类加载器:必须继承java.lang.ClassLoader,下面介绍。
2. java.lang.ClassLoader类介绍
自定义类加载器必须继承自java.lang.ClassLoader,该类的一些重要方法如下所示:
方法 | 说明 |
---|---|
getParent() | 返回加载器的父类加载器 |
loadClass(String name) | 加载名称为name的类,返回的结果是 java.lang.Class类的实例。 |
findClass(String name) | 查找名称为name的类,返回的结果是 java.lang.Class类的实例。 |
findLoadedClass(String name) | 查找名称为name的已经被加载过的类,返回的结果是 java.lang.Class类的实例。 |
defineClass(String name, byte[] b, int off, int len) | 把字节数组b中的内容转换成Java 类,返回的结果是 java.lang.Class类的实例。这个方法被声明为final的。 |
resolveClass(Class<?> c) | 链接指定的Java 类。 |
ClassLoader加载类的过程由loadClass()执行。按照以下优先级加载类:
调用findLoadedClass(String)检查类是否已经加载。
如果父类加载器不为空,则调用父类加载器的loadClass()方法;否则调用启动类加载器的loadClass()方法。
调用findClass(String)方法,该方法找到类对应的字节流后会调用defineClass方法。
3. 其他
每一个java.lang.Class对象都包含一个指向定义该类的类加载器。
对于一个同一个类文件,类加载器不同,得到的将不是同一种类型,即Class对象的equal将返回false。
数组对象由Java运行时创建,数组元素为对象的数组的类加载器与其数组元素相同;数组元素为元素类型的数组的类加载器为null。