一 概述
ClassLoader本身也是一个对象,这个对象主要是用来加载类(是加载class,不是普通对象)。这个类是一个抽象类,不能实例化对象。只要基于二进制的类名,class loader就会尝试去定位和产生用于组成类定义的数据。一种常用的方
定位:找到已经存在的.class,比如lang包下的文件
产生:JVM动态生成class,比如动态代理
式就是将类名为文件名,然后根据文件系统读取class文件。
二进制类名:
任何类名必须是符合Java语言规范的二进制类名,该类名作为参数传递给ClassLoader中的方法
符合Java语言规范的二进制类名
"java.lang.String" //包含包名的全类名
"javax.swing.JSpinner$DefaultEditor"//内部类用$表示
"java.security.KeyStore$Builder$FileBuilder$1"//匿名类用数字表示,1表示第几个内部类
"java.net.URLClassLoader$3$1"
每一个类对象都有一个定义这个类对象的ClassLoader,可以通过getClassLoader()获取这个类加载器。
数组类的类对象不是被ClassLoader产生的,而是JVM运行时自动产生的。数组类的类对象调用getClassLoader()方法返回值与数组中元素的类对象调用getClassLoader()的返回值一样。如果元素类型是原生类型,那么数组类对象调用getClassLoader()的返回值为null。
public class MyTest {
public static void main(String[] args) {
int[] ints=new int[2];
System.out.println(ints.getClass()); //打印class [I 此类并不存在,是JVM动态生成的
MyTest[] myTests=new MyTest[2];
//每个class对象,都包含了定义此对象的ClassLoader,通过getClassLoader获得
System.out.println(MyTest.class.getClassLoader());
System.out.println(myTests.getClass().getClassLoader());
控制台输出:
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$AppClassLoader@18b4aac2
可知:数组类的类对象调用getClassLoader()方法返回值与数组中元素的类对象调用getClassLoader()的返回值一样。
System.out.println(ints.getClass().getClassLoader());
控制台输出:
null
可知:如果元素类型是原生类型,那么数组类对象调用getClassLoader()的返回值为null。
}
}
程序实现ClassLoader类的目的是扩展JVM动态加载类的方式,比如从网络环境加载类等。
ClassLoader使用双亲委托模型去搜索class和资源,每一个ClassLoader都有一个与之相关联的父ClassLoader。当需要搜索class和资源时,在本ClassLoader查找class和资源之前会委托给父ClassLoader去查找class和资源。虚拟机的根ClassLoader是bootstrap class loader,bootstrap class loader没有父加载器,它本身是其他的父加载器。
支持并发加载的加载器被称为parallel capable加载器,parallel capable加载器需要在类初始化是调用ClassLoader.registerAsParallelCapable方法。默认系统的类加载器已经注册了,但是子类仍需注册。
如果不是严格的双亲委托模型,类加载器则需要parallel capable,否则类的加载可能导致死锁,因为所需要保持在整个加载过程。
一般来说,类的来源是文件系统,但是也可能来自于网络或者动态生成。ClassLoader的defineClass方法,将参数中的数组转为class对象。
被类加载器创建的对象的方法和构造方法中可能会引用其他的class,JVM调用loadClass方法去定义被引用的类。
二 构造方法
//类加载是基于双亲委托的,因此需要设置父加载器是谁
//该构造方法就是 使用参数的parent去构建一个新的loader
protected ClassLoader(ClassLoader parent)
//使用系统类加载器作为父加载器去构建一个新的loader
protected ClassLoader() {
this(checkCreateClassLoader(), getSystemClassLoader());
}