目录
序言
这篇我会为大家介绍一下类加载器的双亲委派机制,不过想要了解双亲委派机制还需要一些前置知识,我们得先去了解一下JVM的类加载器.大家可以看下我上篇文章写的类加载器https://blog.csdn.net/weixin_42214548/article/details/109687121,看完这篇文章后相信大家会对类加载器有一个整体的认识,那么再去学习双亲委派机制就不会一脸懵逼了.
介绍
Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象.而且加载某个类的class文件时,Java虚拟机采用的是双亲委派机制,即把请求交由父类处理,它就是一种任务委派模式.
相信大家对上面的介绍还是比较模糊的,我这里再为大家详细的介绍一遍双亲委派机制
所谓双亲委派机制就是当类加载器(程序默认使用系统类加载器AppClassLoader)接收到类加载的请求时,会首先去询问自己的父类加载器(扩展类加载器ExtClassLoader),然后父类加载器也会询问自己的父类加载器(启动类加载器BootStrap ClassLoader),如果当前父类已经是顶级父类了就没有再向上询问的动作了,而是由当前的类加载器去处理这个类加载请求,如果无法处理则会向下处理,交这个类加载的请求交给自己的子类,如果子类也无法处理又会向下处理,交给子类的子类,一直到能处理为止. 而这一整套的流程就叫做双亲委派机制
为什么
上面介绍完了这个双亲委派机制后,相信很多小伙伴就会很疑问了,为什么要这么去设计呢,这样的设计有什么好处吗?
好处当然是有的啦,这里我为大家举个例子: 假设我们创建一个String类,包名为java.lang,那么我们在使用String类的时候,使用的是Java核心类库的String类还是我们自己创建的String类呢?
带着这个疑问我为大家写了一些伪代码
package com.jun.lee.java.lang;
/**
* <Description>
* 测试类
* @author Jun Lee
* @version 1.0
* @createDate 2020/11/14 11:32
* @see com.jun.lee.java.lang
*/
public class String {
static {
System.out.println("大家好呀!!!");
}
}
package com.jun.lee.day2;
/**
* <Description>
*
* @author Jun Lee
* @version 1.0
* @createDate 2020/11/10 22:37
* @see com.jun.lee.day2
*/
public class ClassLoaderTest3 {
public static void main(String[] args) {
String s = new String();
}
}
我们来分析一下代码,我们在程序里面创建了一个java.lang包下的String类,但是Java核心类库中也存在一个java.lang的String类,那么我们在第二段代码中又new 了一个String类,这个String到底是Java核心类库的还是我们自定义的呢.
如果是我们的话,那么肯定会在程序启动后输出一句"大家好呀!!!",带着这样的疑问我们尝试去运行一下.
最后的结果是没有任何输出语句.这也说明了这个new 出来的String类并不是我们自定义的那个String类
原理和好处
原理自然就是因为类加载器的双亲委派机制了,因为String类存在于Java的核心类库当中,所以被启动类加载器加载.
这样的好处就是杜绝了恶意模仿Java核心类,造成JVM崩溃或者是程序信息被泄露的风险,因为模仿的类最终是无法被类加载器加载的.
到此---------------------------------------------------------------------------------------------------------------------------------------------------------------------