类加载器:类加载的工具。我们在Java程序里面用到一个类,JVM首先要把这个类的字节码加载到内存中,并进行处理,这就是类加载器的作用。
Java虚拟机中可以安装多个类加载器,系统默认三个主要的类加载器,每个类负责加载特定位置的类:BootStrap,ExtCalssLoader,AppClassLoader,后面两个也是也是Java类,同样也需要被类加载器所加载,这样就有了第一个被启动的类且不是Java类的加载器BootStrap。BootStrap这个类很特殊,不是Java类,所以不需要被别人加载,是嵌套在JVM内核中的,JVM内核一启动,它也就可以使用了,是用C++语言所写。
JVM中的所有类加载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其需要为其指定一个父类级别的类加载器对象或者默认采用系统类加载器为其父类级别类加载器。
BootStrap作为顶级父加载器,子加载器是ExtCalssLoader,而AppClassLoader又是ExtCalssLoader的子加载器。
BootStrap掌管着JRE/lib/rt.jar的加载,ExtCalssLoader管理着JRE/lib/ext/*.jar的加载,AppClassLoader管理着ClassPath指定路径和所有jar的加载。
除了系统默认提供的三个类加载器,我们还可以继承ClassLoader类去实现自定义的类加载器。自定义的类加载器需要指定父加载器。
类加载器的委托机制
当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
首先当前线程的类加载器去加载线程中的第一个类。
如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。
还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
每个类加载器加载类时,又先委托给其上级类加载器。
当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?
对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下的itcast.jar包中后,运行结果为ExtClassLoader的原因。