类加载器和双亲委派模型
类加载器:通过一个类的全限定名来获取描述该类的二进制字节流。(Java虚拟机外部实现)
对于任意一个类,都是由加载它的类加载器和这个类本身共同确立在Java虚拟机中的唯一性。
同一个class文件,如果一个由虚拟机应用程序类加载器加载(虚拟机本身的类加载器),一个由自定义类加载器加载,那么它们将是2个独立的类。
- 启动类加载器(Bootstrap Class Loader):负责加载存放于<JAVA_HOME>\lib目录下,或者被-Xbootclasspath参数所指定的路径中存放的类库加载到虚拟机内存中。(文件识别名要符合要求,不符合的也不会被加载)
- 扩展类加载器(Extension Class Loader):这个类加载器是在类sun.misc.Launcher$ExtClassLoader 中以Java代码的形式实现的。它负责加载<JAVA_HOME>\lib\ext目录中,或者被java.ext.dirs系统变量所指定的路径中所有的类库。
- 应用程序类加载器(Application Class Loader):这个类加载器由 sun.misc.Launcher$AppClassLoader来实现。由于应用程序类加载器是ClassLoader类中的getSystemClassLoader()方法的返回值,所以有些场合中也称它为“系统类加载器”。它负责加载用户类路径上所有的类库,开发者同样可以直接在代码中使用这个类加载器。如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
JDK 9之前的Java应用都是由这三种类加载器互相配合来完成加载的,用户还可以加入自定义的类加载器来进行拓展。
图7-2中展示的各种类加载器之间的层次关系被称为类加载器的“双亲委派模型”。双亲委派模型要求除了顶层的启动类加载器之外,其余的类加载器都应有自己的父类加载器(这里的加载器是用的组合形式,一般不是继承)。
双亲委派模型的工作过程:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。
使用双亲委派模型的好处:Java中的类随着它的类加载器一起具备了一种带有优先级的关系。
例如类java.lang.Object,它存放在rt.jar之中(启动类加载器文件下),无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都能够保证是同一个类。反之,如果没有使用双亲委派模型,都由各个 类加载器自行去加载的话,如果用户自己也编写了一个名为java.lang.Object的类,并放在程序的ClassPath中,那系统中就会出现多个不同的Object类
本文地址:https://blog.csdn.net/weixin_44988663/article/details/107587456