00:00
接着呢,咱们来讲一个新的内容,叫做双亲委派机制,前面的话呢,我们已经介绍过了,呃,几种类的不同的加载器,它们之间的一个关系和使用的细节需要大家掌握,那下边呢,我们再来谈一个比较重要的内容,叫做双亲尾派机制,那一条双亲啊,右尾派还是个什么机制,似乎呢很复杂,但其实呢比较简单啊,那这个呢,在面试当中也经常被问到说哎,你能不能介绍一下什么是叫做双亲委派机制,或者说它的这个工作原理是什么?那有同学就懵了哈,其实呢,不难啊,之所以你不会答呢,是因为你没有接触过它而已啊。那下边我们来解解释一下什么叫做呃双击违约机制啊,首先我们引入一下啊,说Java虚拟呢,对class文件呢,采用的叫按需加载的方式,就是你什么时候需要我对应的这个类了,我们再给你做一个及时的加载,然后生成内存中的一个大的class的对象,嗯,加载的时候呢,这里边提到了叫做双亲尾拍模式。
01:00
呃,交由副类处理我们的请求,它是一种任务委派模式,呃,具体的细节呢?呃,得下边来讲解了,那讲解这个工作原理之前呢,咱们先来看这样的一个问题。好,那我们在这个第二张JAVA1这个包下呢,我先创建一个类啊,这个类呢非常的简单啊,关于string的一个测试啊,在这里边呢,我写一个没方法,哎,在没方法里边,我就来创建一个字符串。然后呢,我做一个输出说hello,比如说啊,我们叫哎,比如艾特硅谷点com,哎,这咱们上顾的这个网址啊,行诶非常简单哈,我们就创建了一个string字符串的对象,然后做了一个输出语句,那直径的话呢,毫无疑问就是把我们这个输出语句呢做了一个打印。呃,打印的目的主要是呃证明一下我们这个程序确实执行了啊,在输出信息之前呢,有了一个string对象的创建,呃,是这样的一个过程,好的这个呢就完事了,那接着呢,我们想演示个情况呢,是这样的,我们在当前的这个module是吧,这个我们当前的这个模块啊src下呢,我去创建一个包,这个包呢名字比较特别,我就想创建为Java点浪包,有同学诶有同学想诶还可以这样做吗?创建完以后你发现是没有报错的,诶是可以这样做的,只不过呢,大家想我开发中从来没有错过啊,那没有做过就对了,因为我们开发中呢也不能这样做啊,我现在演示呢,其实是一个错误的情况啊呃,但是呢,你要说我想都没想过是吧?呃,那可能有点差点意思哈,那也可以想一想,就生活当中呢,有些我们说不太好的一些事情,或者叫坏事吧,你不能做,那可以想一想是吧,扩展扩展这个思路哈,呃,那Java点这个浪包下呢,我们在。
02:47
New下边,呃,New一个class,比如说我去就new一个string,大家看啊,我们在这个浪包下自己造了一个类,这个类呢,也叫做string,所以这个string的完整路径就是扎点浪包下的string,哎,就成这么个情况了啊呃,那现在我创建完以后啊,就最简单啊,那大家回过来再看,我们这个时候造一个对象,这个对象到底是我们RT点炸包下的核心API string,还是我们自定义的string呢?
03:17
哎,目前来看的话,好像也很难证明到底是谁,那我不妨呢,在咱们自定义的这个词令当中啊,诶,我写一个静态代码块。哎,静态码块啊,在静态代码块里边,我们写一个语句说,哎,我是自定义的,哎这个string类的,哎静态代码块好就写完了,那么大家想一下,我们这个类呢,如果被加载使用的话呢,会不会执行这个静态码块呢?哎,很显然是会的,对吧,那我们前面呢,是不是讲过这个类的初始化啊,类的初始化第三个阶段啊,我已经把这个结果说出来了,就是这个,呃,静态代码块在哪个阶段呢?被调用的呢?就是我们说第三个阶段叫做初始化阶段,诶我们会把这个静态代码块,包括静态变量的显示赋值是吧?诶都会给它放在诶叫做CL这样的一个构造器的方法中啊,做一个执行,好这个我们就知道这个事儿了,我加了一个静态代码块以后再回过来,诶大家看此时呢,我们诶扭了个对象,然后呢,有同学说这样写肯定还是核心API,那不妨呢,我这给你加上一个Java点,哎浪包其其实加不加都一样啊。
04:32
哎,加完了是吧,加完以后呢,我们这时候再做一个调用。诶大家看啊,这时候呢,并没有报错,也没有执行我们刚才这个静态代码块啊,你想想没有执行静态代代码块,说明我们这时候new的string啊,它就不应该是咱们自定义的这个string嘛,啊,因为你想想啊,如果我们这时候造个对象,我既然造对象了,肯定要加载类了,那我加载类如果是用的自定义类,那这个呢,进内代码块是一定要执行,所以就会输出,那现在没有输出说明不是它,那就意味着咱们当前的这个string啊,用的其实还是核心API里面的。
05:11
啊,这就是我们,呃,目前呢,从这个结论来看的话呢,是这样的一种情况啊,那这种情况里边蕴含了其实就是呃叫双亲委派机制。大家想,如果说我们现在执行的是你自定义的这个string,那是不是就很崩溃了?你想想啊,我们写了一个项目,这个项目里边的话呢,我们字符串肯定是大家都要用的啊,然后现在我自定义这个string,通过网络呢传给你,你一打开,你把它加载到你的这个程序当中啊,一打开或者一运行整个呢项目不是就挂掉了,或者我在这个你运行的过程当中,我做一些恶意的数据的一些窃取等等,那你整个这个项目是不是就废了?啊,那为了呢,对我们这个项目进行一个保护,防止恶意攻击呢,诶我们引入了一个叫哎双亲委派机制,那它的这个原理是什么呢?我们看一下啊,哎,先来看左边这个内容,分成了这样的三步。
06:05
说呀,如果一个类加载器收到了类加载的请求,他并不会自己先去加载,而是呢,把这个请求委托给负类的加载器去执行,比如说咱们刚才呢,这个代码我需要呢,去new一个string型的,呃,New一个string的对象,那我这呢需要加载string这个类了,那按说呢,似乎是呃想用这个似的是吧,你要是这个类加载的话呢,大家想我们自定义的类,你要想加载的话呢,应该是用诶系统类加载器,或者叫应用程序类加载器啊,就那个APP class loader,呃,但是呢,这时候我们说啊,你先别着急去加载呢,你先委托给你的负类加载器去加载,那也就是说呢,呃,APP class so呢,会向上委托找到它的负类,叫做extension,诶,Class load,那如果负类加载器还存在,其负类加载器则进一步向上委托依次递归啊,最终呢,请求将到达顶层的启动类加载器啊,不管你是呃,下边自定义的也好,怎么样也好。
07:05
就是一层层的往上委托,一直会到引导类加载器,诶其实这个过程呢,大家想是不是特别像我们这个类的加载是吧,我们类的加载的时候呢,你子类的加载之前是不是一定要父类的加载啊,一直到最上边object类需要加载啊,其实是有点像的啊。好,现在呢,我们是委托,就是你这个类要加载的时候呢,我们需要使用加载器,这个加载器呢,一直向上委托,直到引导类啊,或者叫启动类加载器到bootrap class so这了行,然后如果负类加载器可以完成类的加载任务,那就成功返回。倘若负类加载器呢,无法完成加载任务,子类加载器呢,才会尝试自己去加载,这就是我们所说的双亲尾派模式,那以刚才的例子来说,咱们这个在程序当中要去new个词string了啊,New个词string了啊,似乎呢,想用我们的这个自定义类,那自定类的话呢,就应该用系列系统类加载器,性类加载器呢,网上委托一直到了引导类加载器,引导类加载器看一下,说你现在想new个string,说我能做吗?一看你是Java点浪宝下的,哎,大家还记不记得咱们上面讲这个引导类加载器的时候。
08:17
嗯,这是扩展类,诶讲阴道类加载器的时候,你看我们说过啊,它呢是负责加载这个Java开头的,Java X开头或者三开头的这个包下的一些类,一看你是Java开头的,那我们引导类加的就说了,说这事儿啊归我管啊,这事归我管,我来加载你这个string,哎,那所以呢,我们接下来你new的这个对象就是咱们这个核心API里边的那个string了,所以呢,就不再去是你这个,呃,说白了就是我们一旦引导类加载器它加载完以后呢,就不会再去向下委托了。哎,是这个情况啊,那比如说咱们自定义的一个啊,像比如我下边这个这个再写一下啊写谁呢?写我们这个string test test,我写个test等于new一个,诶string test,哎,有个它了是吧,然后呢,我们输出一下test点。
09:11
嗯,第二我们get一个class.get class loader。那我们自定义这个对象,它的所属类的类的加载器,毫无疑问呢,就是属于叫系统类加载器了。你看诶,这就是系统加器,诶它的这个过程呢,比我们刚才上面说的这个稍微多一个环节,就是首先呢,我们去造它的对象,那需要把这个类呢加载,这类加载呢,也是先有这个信用类加载器,然后一是向肠委托到阴道类加载器,阴道类加载器一看说你这个哥们儿啊,你所在的这个包啊,我不管啊,你这com开头了我不管,不管的话呢,它就会向下继续委托给扩展类加载器,扩展类加载器一看说呢,你这也不在我加载的这个路径下。嗯,应用程序再往上一个。这诶扩产类加载器呢,它加载路径这不我们也说过了是吧,诶一看呢,你也不在我这个路径下,那我也不管,诶那都不管了,下边就到系统类,系统类一看说那我管,所以最后呢,我们输出结果就是由诶系统类加载器进行一个加载啊这就我们说的叫双亲尾派模型啊,应该呢是说清楚了,那举一个生活中的例子。
10:23
生活中的例子,举个什么例子呢?比如说嗯,比如这个一个小朋友是吧,小朋友现在拿了一个苹果,那按卓呢,他就直接可以吃了,但是呢,出于礼貌呢,他问说妈,你吃吗?哎,他就问他妈是吧?呃,他妈一看呢说,诶这个奶奶还在这儿呢,他就问说妈,你吃吗?呃,然后呢,就问给到这个老人了,老人一看说诶,我吃是吧?呃,这个老人就拿着就吃了,小孩呢,跟他妈呢,呃,就两个人就流口水就可以了。呃,就只能有一个类加载器,就是你这苹果只能一个人吃啊,你不能说几个人分一分,嗯,没这回事啊,一个类呢,只能有只只,只需要由一个加载器加载就可以了,那这是一种情况啊,然后第二种情况呢,这个小孩呢,拿着苹果说,诶妈你尺吗?妈尺码一直到他奶奶这儿了,然后呢,呃,这个这个老人呢一看说哎呀,你这个苹果呢,看着有点硬,说我都没有牙了,我就不吃了,然后就给这个她的儿媳妇了,是吧?呃,这个孩子妈呢一看说呀,这个苹果呢,一看有点酸,说说要不你吃吧。
11:23
啊,这都欺负孩子呢是吧?哎,然后呢,就就给到孩子了,孩子说那我正好喜欢吃酸的跟硬的,哎,那这个孩子就吃了,哎就是它的上层啊负类加载器如果不加载的话呢,那我们就委托给这个子类加载器加载,那有没有可能就是说说这个子类也不加载,我也不管这不会的啊这个这肯定是有加载加载器的,咱们默认的话呢,就是呃,系统类加载器进行加载。除非呢,后边你再去自定义的加载器啊,是这样子的,好,这呢就是我们叫双亲委派机制啊,那回过来大家再过来看我们这个string啊,我们在,呃,顺着刚才这个思路呢,我们再写一个小的代码啊,我们在这个string string的类里边,我写一个main方法,简单的写一个输出语句说hello,诶,String。
12:09
诶保存一下,那此时呢,我们去执行,大家想想会出现什么问题呢。我写了个main方法啊好,我们跑一下。大家看此时呢,出现错误了,说呢,在你这个string类中啊,我找不到这个没方法,说没方法呢,这样来定义,哎这样子,诶那这个原因呢,大家应该也会解释了,就是我们现在呢,想去执行main方法,那酶方法所在的类呢,就需要被加载,那一加载呢,实际上一层层网上委托就交给了阴道类加载器啊,或者叫行动力加载器,它加载了此轮以后呢,呃,去执行酶方法,那我们知道核心API里边的咱们常用的那个字母串啊,它是没有酶方法的。所以呢,这里边就报了一个说我找不到没方法,就是根本就没有试图去加在我们自定义的这个string内,就完全忽略掉你了,诶就会报这样的一个错误信息啊,大家知道这个原因就可以了啊,我们把这个错误信息呢,把它CTRLC啊咱们粘到这。
13:10
好,那么通过刚才这个例子讲解呢,大家应该比较清楚什么叫做双亲委派机制了,那下次面试呢,如果问到这个问题,哎,你是可以通过刚才的例子给他解释清楚的。
我来说两句