双亲委派机制是当类加载器需要加载某一个.class字节码文件时,则首先会把这个任务委托给他的上级类加载器,递归这个操作,如果上级没有加载该.class文件,自己才会去加载这个.class。这是一种任务委派模式。
用一个小故事来加深大家的印象:
1、你看到餐桌上有个鸡腿,看到麻麻非常幸苦。你就说:麻麻你次这个鸡腿吧。麻麻又看到桌上的奶奶,就讲妈:次这个鸡腿补补身子吧。奶奶高兴的说:我媳妇孝顺啊,我今天也来尝尝这个孝顺味道的鸡腿啦。
2、你看到餐桌上有个鸡腿,看到麻麻非常幸苦。你就说:麻麻你次这个鸡腿吧。麻麻又看到桌上奶奶在,就讲妈:次这个鸡腿补补身子把。奶奶高兴的说:我媳妇有这个孝顺心就好了,你每天上班次外卖,对身体不好,这个鸡腿给你次。麻麻拿到手上,又反手把鸡腿夹给我,讲:这个鸡腿还是得你次,你现在正在长身体,不补一补长不高。⛹️♂️
这就是双亲委派机制,不知道看完这个餐桌小故事,大家有没有懂勒。
我在我自己的项目中创建了 一个java.lang的包 ,然后创建了一个 String 类。
再准备一个测试类,引用这个String类。
String 类 里面就一个静态代码块。
代码可以运行,输出如下:
并没有输出我的String 里面的static 静态代码块,证明使用的仍然是 jdk 自带的。
原因是什么呢?
一步一步分析。
我们自定义一个类,你要想加载的话,应该是用 Application ClassLoader(系统类加载器、应用程序加载器)进行加载。但是这个时候又牵扯到了 双亲委派机制。
1、当我们要加载这个自定义String时,
2、先是让应用程序加载器(Application ClassLoader)加载,但是发现它上面还有扩展类加载器(Extension ClassLoader)
3、接着委托给扩展类加载器(Extension ClassLoader),突然发现它上面还有Bootstrap ClassLoader (启动类加载器)
4、就又接着委托到了Bootstrap ClassLoader (启动类加载器)。启动加载器一看,这不是 java.lang 包下的吗,这是我的任务啊,急忙把他加载啦,然后成功返回。所以这里使用的 new String() 实际使用的还是 java 中 String。
这样子可以防止什么样问题的发生呢?
你想啊,你写了一个项目,里面用了Jdk 核心类,像String.java,Integer.java,Date.java这种核心类,如果这种核心类能够被随意更改,第一、这很有可能导致整个项目的崩溃,第二、会影响到Java 虚拟机的稳定性。