类加载器及其委托机制的深入分析
类加载器
Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader。
类加载器也是Java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap。
它不需要别人加载,是被嵌套在JVM内核中的。
System.class.getClassLoader(); // return null,System是由BootStrapClassLoader加载的
类加载器之间的父子关系和管辖范围
- BootStrap ---- JRE/lib/rt.jar (System)
- ExtClassLoader ---- JRE/lib/ext/*.jar // 可以将自己写的工具类放置在ext目录下,让ext类加载自动加载
- AppClassLoader ---- classpath指定的所有jar或目录
- MyClassLoader ---- 自己指定的特殊目录(以上所有的类加载都无法加载,只有自定义的类加载器才可以加载)
类加载器树,可以自定义继承了ClassLoader的类加载,并指定其父类加载器,则可以将自定义的类加载器挂到类加载器树上。
Java虚拟机中的所有类加载器采用具有父子关系的树形结构进行组织,在实例化每个类加载器对象时, 需要为其指定一个父级类加载器对象或者默认采用系统类加载器为其父级类加载。
类加载器的委托机制 每个ClassLoader本身只能分别加载特定位置和目录的类,但他们可以委托其他的类加载器去加载类,这就是类加载器的委托模式。
类加载器一级级委托到Bootstrap类加载器,当BootStrap无法加载到当前所要加载的类时,然后一级级回退到孙在类加载器去进行真正的加载。 当回退到最初的类加载器时,如果它自己也不能完成类的加载,那就抛出ClassNotFoundException异常。
能不能自己写一个命名为java.lang.System的类? 为了不让我们自己写System类,类加载采用委托机制,这样可以保证父类加载器优先,也就是总是使用父类能找到的类,这样总是使用java系统提供的System。
当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢? 首先当前线程的类加载器去加载线程中的第一个类。
如果类A中引用了类B,Java虚拟机将使用加载类A的类加载器来加载类B。
还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
每个类加载器加载类时,又先委托给其上级类加载器。
当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不到,则抛出ClassNotFoundException,不是再去找发起者类加载器的儿子, 因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?
自定义类加载器的编写原理分析
编写自己的类加载器,自定义的类加载器必须继承ClassLoader
loadClass方法与findClass方法 defineClass方法
模板方法设计模式
父类(定义流程,即是方法调用的顺序)
子类1(子类覆写父类的方法)
子类2(子类覆写父类的方法)
定义一个抽象父类,父类定义一个流程,父类在执行流程的过程中,遇到某些局部细节无法确定,就把它定义成抽象方法, 等待子类覆写这个方法,留给它的子类来完成这个工作。