类加载器
所谓类加载器就是将.class文件加载进内存的工具。
JVM中可以安装多个类加载器,系统默认三个主要类加载器,BootSrap,ExtClassLoader和AppClassLoader,每个类加载器负责加载特定位置的类。
类加载器也是Java类,既然他是Java类,他本身也要被类加载器加载,显然必须有第一个类不是Java类,这正是BootStrup,BootStrup是用C++编写并内置在JVM中的。
JVM中的所有类加载器采用具有父子关系的树形结构进行组织,在实例化每个类加载器对象时,需要对其指定一个父级类加载器对象或者默认采用系统类加载器为其父级类加载。
类加载器之间的父子关系及管辖范围图
类加载器的委托机制
当JVM要加载一个类时,到底派出哪个类加载器去加载呢?
首先当前线程的类加载器去加载线程中的第一个类。
如果类A中引用了类B,JVM将使用加载类A的类加载器来加载类B。
还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
每个ClassLoader本身只能分别加载特定位置和目录中的类,但它们可以委托其他的类加载器去加载,这就是类加载器的委托模式。
类加载器一级级委托到BootStrap类加载器,当BootStrap无法加载当前所要加载的类时,然后才一级级回退到子孙类加载器去进行真正的加载。
当回退到最初的类加载器时,如果它自己也不能完成类的加载,则抛出ClassNoFoundException异常。
自定义类加载器
自定义的类加载器必须继承ClassLoader
ClassLoader中的三个主要方法:
protected Class<?> loadClass(String name): 加载指定名称的字节码文件。
protected Class<?> findClass(String name): 查找指定名称的字节码文件,当查找到指定字节码文件后,该方法内部会调用
loadClass方法将该字节码文件加载进内存。
protected final Class<?> defineClass(String name,byte[] b, int off,int len):将一个 byte 数组转换为 Class 类的实例。