类加载器的分类
1 三个类加载器
常见的类加载器有三种,每个类加载器负责加载不同位置的类:
1)Bootstrap 根类加载器;
2)ExtClassLoader 扩展类加载器;
3)AppClassLoader 系统/应用类加载器;
那么这三种类加载器各有什么作用或者有什么区别呢?
他们三个加载的范围是不一样的。
说明:
1)Bootstrap 根类加载器
它是最顶级的类加载器,它的底层不是一个类,而是有c++一段代码生成的。
用来加载类文件不是我们自己书写的,而是负责Java核心类的,比如System,String等。
因为只有把所有类加载到内存中,我们才可以使用。
2)ExtClassLoader 扩展类加载器
加载的是扩展类的,我们是用不到的,都是jdk内部自己使用的。
3)AppClassLoader 系统/应用类加载器
是用来加载我们自己书写的类的.class文件的,比如 Person 、Student等
是用来加载ClassPath 指定的所有jar或目录,ClassPath表示存放类路径的。我们如果不配置ClassPath,那么就表示当前文件夹。
在idea环境下的ClassPath是out目录。在out目录存放的都是我们书写好的class文件,也就是说 AppClassLoader 类加载器是用来加载我们书写的out目录下的class文件。
2 三个类加载器的关系
Bootstrap 是根,它是最顶级的类加载器,它的底层不是一个类,而是有c++一段代码生成的。
ExtClassLoader extends Bootstrap { }
AppClassLoader extends ExtClassLoader { }
备注:对于类加载器 ExtClassLoader 和 AppClassLoader 也要被类加载器加载才能使用。
他们是被各自的父类加载器加载的。
即:ExtClassLoader 是被 Bootstrap 加载器加载的。
AppClassLoader 是被 ExtClassLoader 加载器加载的。
3 获取一个类的类加载器
需求:演示类加载器的父子关系。
getClassLoader() 获取该类的类加载器
代码演示如下所示:
分析:如何获取一个类的类加载器呢?
如果想获得当前类的加载器,那么首先必须获得当前类的字节码文件对象,而这个字节码文件对象属于Class类型,我们可以使用 Class类中的getClassLoader()函数来获得类加载器:
ClassLoader getClassLoader() 返回该类的类加载器
AppClassLoader:加载classPath中的所有的类,也就是我们自己写的那些类!
注意:类加载器,也是一个类,也需要被加载。一般类加载器都是被父类加载器加载的!
获取父类加载器的方法:使用ClassLoader 类中的getParent()返回委托的父类加载器 。
说明:AppClassLoader是被ExtClassLoader加载的!
ExtClassLoader肯定也是一个类,需要被父加载,它的父亲是BootStrap。
那么问题来了:如果这个类加载器也需要被人加载,那么就没有尽头了!因此,BootStrap是不需要被加载的。
因为它不是一个Java类。它是用C++实现的一段代码。
也就是说,jvm虚拟机一启动就会运行C++实现的这段代码,那么BootStrap类一旦被启动就会开始加载他下面的子类了。
注意:最顶级的类加载器不是Java类,而是C++实现的代码。