00:00
好,那咱们呢,就是刚才呢,是看了一下这个class呢,一个简单的这个注释,那包括launcher里边这个核心的一个操作,对吧?那下面的话呢,咱们来熟悉一下class load里边的这个主要的方法有哪些,那从这个继承关系上,我们看到这个class so呢,内部呢,我这放了是四个方法,那其实它内部方法比较多,那比较重要的三个方法呢,一个呢叫load class,一个呢叫find class,还有一个呢叫做DeFine class,就是这样的三个方法是最核心的方法。那除了这三个之外呢,当然还有其他的一些方法啊,那这个克拉那呢,它是一个抽象类,但是它内部呢,注意并没有抽象方法啊,有一些方法呢,它是一些这个方法体是空的一些方法,这个倒是有,比如说这个find class啊,它就是好,那首先的话呢,我们针对这个class呢,它内部的这几个方法呢,咱们进行一个介绍啊,进行一个介绍。首先的话呢,我们看到一个方法叫做get parent,那get parent呢,就是我们这个在咱的代码当中啊,咱们那会儿讲这个具体的操作的时候呢,是不是调用过这个叫get parent是吧?嗯,在上边那get parent实际上就获取当前这个类加载器,它的负类加载器是谁。
01:11
对吧,那举例呢,比如说咱们刚才提到了,像这个launcher里边啊,咱们看下这个构造器里边这个呢,是你对应的,嗯,构造器里边这个呢,是我们对应的是不是叫。扩展类加载器对吧,然后呢,我们把这个扩展类加载器呢,作为咱们这个应用程序类加载器的一个负类出现的,那相当于呢,就是具体呢parent就拿它来进行一个赋值,那当我们通过这个系统类加载器呢,去get判的时候呢,这不就把这个扩展类加载器呢,就获取到了嘛,对吧,咱们在这个哎long这个class里边。A class loader。在这是吧,它这里边呢,这不我们也能找到它对应的这样的一个属性嘛,这个往上拽。咱们那会儿呢,不也带大家看了是吧,然后那个get方法呢,其实就是关于这个属性的一个get方法,OK,它俩就是匹配的,行,这个不用多说,然后呢,咱们来看一下下一个方法叫做load class,这个load class呢,咱们在前面讲这个。
02:07
这个类的加载的时候啊,咱们不是说过这个事儿吗?说我们去加载一个类的时候,咱们主动的你要加载可以呢,使用这个叫class for name还可以呢,使用就叫load class是吧?哎,我们主动的去加载一个类啊,行,那这个load class呢,就是在咱们class loader里边定义的一个方法。哎,定义的一个方法,那这个参数呢,是需要我们去写一个这个权利名啊,写完之后呢,调用这个方法,他就找这个权利名所对应的那个相应位置上的一个资金法文件。当然呢,这个资源码文件呢,可能是一个资源码文,也可能来自于这个网络当中传输过来的二进制数据,对吧,二进制流的这个数据,然后最终呢,是把它还原成一个大的class的一个实例,那如果要没有找到呢,哎,就返回叫class not found exception。好,那这个方法当中呢,我们说逻辑呢,就是实现双亲委派机制的,那我们这块呢,对这个load class这个方法呢,咱们进行一个说明。
03:02
那在咱们这个class里边啊,CTRL一下找到咱们叫load class。行,那这呢就是我们要说的这个方法对吧,这个load class这个方法呢,它内部呢是有具体的实现了,那又调了一个load class是一个重载的方法,那这个第二个参数呢,叫做resolve解析的意思啊,这写的是个false啊IG呢,就是我们在这个加载的同时呢,要不要解析呢?那这个就是说不需要解析,OK好这呢就是我们说这个load class这个核心,那这样的话呢,我把这个方法从这到这啊把它CTRLC咱们粘出来。这个方法呢,实际上是我们这里边要提到的最核心的一个方法。好,我就放到这儿了,这个呢是关于我们的叫做哎load哎class这个方法的一个剖析,好那这块呢,我把相应的这个说明呢,咱们就写到这儿啊,所以呢,咱们就把这个代码呢给大家粘过来,大家注意看,当我们去调用那这块为了说明的方便,我需要用一个结构啊,我把这个呢截一下。
04:06
啊过来,嗯,找到咱们刚才这个方法。看这啊好,那咱们现在呢,是不是要调这个load class,假设假设啊,咱们现在呢,是使用的这个系统类加载器,咱们去调一个load class,咱希望呢,诶我我在我在上面得这样写是吧,比如咱们现在有一个测试。来测试代码,这个测试代码是这样的啊,我通过这个class loader点叫get system。哎,Class loader是吧,然后第二第一个load,哎,Class。那这里边呢,咱们就写了一个具体的啊,比如说我们要自定义的类的话呢,就com点,比如硅谷点Java下的关于user啊,它呢一个加载啊,这就是咱们对应的这个测试代码,那有了这个测试代码之后呢,下边呢就涉及到。哎,对如下方法的一个调用是吧,哎,我们就过来了啊,那我们来看一下,要想加载这个user呢,它这个过程是什么样子的。
05:11
那调练方法的时候呢,我们这儿写的是一个就是这个字符串呗,这个位置呢,咱们刚才看到这写的是false啊,所以在这我们先说明一下这个参数,这个resolve它的一个意思。啊,它的一个意思就是,如果呢,它是一个false,哎写是触吧,True的时候呢,是什么意思呢,就是嗯,加载class的同时。哎,然后呢,哎,同时来进行解析操作,来进行解析操作,就如果是个true的话,那false呢,就意味着你不需要解析啊,咱们刚才看到这块呢,是不是调用的是一个false是吧?那就不需要解析这个情况好,然后过来之后呢,我们接着去分析,这有个同步操作,就是表示呢,我们去加载一个类的时候呢,我们说是不是只能是同步的,就只能加载一次是吧。
06:02
哎,同步操作啊,保证啊只能加载一次,就是如果呢,我们多个线程去访问这个加载操作的话呢,我们这时候呢,得有个同步的操作,OK,然后再往下说呢,这里边儿我们调的叫find loaded class,诶这个呢是需要我们说明一下,你看这个注释写的其实也很清楚,首先的话呢,去检查一下你这个class是不是已经被加载过了。哎,说的很很明确啊,这个杨ID呢,就是哎,就是首先在缓存中。啊,这个判断啊,是否已经加载同名的这个类。咱们知道呢,这个类的加载器,咱们去调这个方法的时候,那每一个类的加载器,咱们说都有一个命名空间,对吧,咱们这不前面在这讲的命名空间。没问题对吧,那在同一个命名空间当中啊,咱们说是不会出现这个同名的两个类的啊,所以说我们针对于比如说这个应用程序类加载器,咱们再去这个加载,想加载某个类的话呢,我先看一下,那我是不是在我的这个命名空间当中已经加载了某一个类了,那对应的就是find loaded class,那这个方法我们在这也可以简单看一下啊,把它点开啊,想加载这个名呢,检查一下这个名呢,看是不是已经存在了是吧?那如果说这个名呢,这个不存在啊,这个返回是个no。
07:23
啊,否则的话呢,这块我们就进行一个加载,是这意思吧,OK啊好拨过来,然后这块呢,就是判断一下你是不是已经存在了,那如果说呢,这个已经存在了,那这个呢,它就会有值,那这个呢,一辅这个就进不去了。啊,这个到这也进不去了是吧,然后你这呢也是个false说明呢,你这也不需要进行解析啊,这个就是是否进行。哎,这个解析操作是吧,哎,这样一个问题,那如果缓存中也有,这不就直接return了这个C了吗?那这是我们说的这个有的情况下,那如果你是首次加载一个类,那肯定这块呢,缓存中是没有的,对吧,那就意味着我们返回的这就是一个no,那返回是一个no,那接下来啊,这是获取这个时间啊,主要往下看,这有一个叫parent。
08:09
好,那对于咱们说这个叫呃应用程序类加载器来讲,我们它的这个parent呢,是不是肯定不是个now啊,这个parent呢,就相当于是叫呃获取当前类加载器的负类加载器。那如果呢,你是应用程序类加载器,或者叫系统类加载器,它的负类呢,是不是就是扩展类加载器了,行,那就比如说咱们现在用的就是这个系统类加载器,这个parent呢,显然就不是no,对吧?Parent要不是no,那紧接着大家会发现我们要调parent的叫load class。那现在又重复的是不是调了一下这个方法,方法里边自己调自己这个递归对吧?好,那这呢,我们表达的意思其实呢,就涉及到了咱们的双亲委派机制啊,就是如果存在负类加载器,那则是不是调用负类加载器,那进行是不是类的一个加载啊。
09:01
咱们这个双亲尾拍机制是不是就是这样的一个说法,咱们在下边呢,咱们讲上篇的时候其实讲到过对吧,那这块我们稍微的再这个,哎,啰嗦一下,看看它这里边这个场景。啊嗯,没在这儿了,那双亲尾外机是什么意思啊,就是我们这个假设呢,是性统类加载器,它要呃试图加载个类啊,他呢去加载,那他先委托给他的副类,它的负类呢,也接着往上去委托,那如果引导了下期呢,发现不下载,他再依次的往下是吧,这就是一个呃双亲委派机制,好那我们这块呢再回过来。现在的话呢,我们针对于这个,诶应用程序类加载器它呢,是不是就存在负类啊,好,那我们就按照这个程序执行的顺序,咱们就往上跑啊,这个T呢,它是一个,呃,应用程序类的它的parent是一个扩展类,那扩展类这块呢,又调了一个load class,好再回过来假设呢,咱们现在加载的就是一个自定义类,咱知道呢,应该是用系统类加载器加载的是吧?但是现在呢,我们把这个类呢委托给了他的parent parent调了一个方法,那缓存中呢,假设也没有,假设没有就也进来了啊呃,那他去在parent注意此时的这个parent的话呢,针对咱们扩展类价驶器来讲,他的parent是不是就是个no了,那就蹦到这儿了啊,那就这个else是吧,那这个else意味着什么呢?就是我们的parent,相当于它是哎,等等于not。
10:20
它为no,那判为no是什么场景呢?那就是对应的就是本这叫什么?哎,负类加载器是是不是引导类加载器吧。对吧?哎,负类加器是引导类加载器,当然你说引导类加载器它的parent哪,当然还是no嘛,是吧?嗯,当然一般呢,咱们不就不说引导类加载器,咱们光看到class里边有个parent属性对吧?行,那通过呢,我们扩展类加载器,你再去找它的parent的时候,那我们这个是个no,那就调下边这个,下边这个呢叫find bootrap class or no,那一看这个就知道,诶确实是这个引导类加载器的这样一个逻辑对吧?那我们针对于你这个扩展类加器,它的这个parent这块啊,它来调这块就调到这了啊在这里边,哎,我们这块呢,就判断一下跟刚才这个逻辑类似啊,看看是不是已经在我们的缓存当中呢,是存在了是吧?那那如果说呢,这个我们可以去加载,那我们就这块呢进行个加载,如果不应该由我们阴道类加载器去加载,那我们就不去加载。
11:20
啊,那我们就不去加载,是不是有个具体的check这样一个逻辑是吧?好,那假设呢,咱们现在加载的就是user这样的类,那显然呢,不应该有阴道类去加载去加载,那这时候返回这个C,注意是不是就是个no啊。对吧,哎,C是个no,那这时候咱们这个调的方法,注意是扩展类加压器里的啊,就我们刚才那会儿呢,调到这个方法里边的,那当这个是一个no的话,我们就蹦到这儿了,说C呢是一个闹,那就相当于是我们当前。当前类的加,呃当然这块呢,咱们是呃执行的这个,或者执行这个呃,当前类的加载器的这个应该说叫负类呃加载器。
12:01
啊,相当于是胃。哎,加载此类是吧,这是一种成情况,那还有一种情况是什么呢?就是我们如果掉到这儿。那调到这儿来看的话呢,就相当于是那个当前类的加载器未加载是吧。哎,胃加在啊此类是吧,那如果你当前这个,嗯,就是我们调用这个阴道类加载器加载的时候呢,发现是个no啊,是个nor时候怎么办呢?说如if still not found then invo find class in order to find the the class,就是这个时候呢,我们需要调用当前这个类的。Class方法。调用,哎当前哎叫什么呀,哎class load的哎find,哎,Class这样的方法,那注意啊,咱们刚才呢,是在你这个扩展类加载器这里边,你这块呢,调它的这个呃阴道类加载器的时候,那显然呢不加载是吧,那不加载时候呢,就蹦到这儿了,那现在这时候呢,调find class是调的咱们是是扩展类加载器里边这个find class啊。
13:10
对吧,那这个发class咱们一会儿呢去展开说它,那咱们知道的就是对于这个扩展类加载器来讲,它是不是也不加载这个user是吧,所以这时候咱们知道这个事儿啊,调完它以后呢,其实这个C还是个nor啊,C还是个no这块返回的,这不就是个闹吗。这就个no是吧,那这个no给了谁呢?给了咱们最开始这个别蒙了啊,咱们现在这不是涉及到一个这样个事儿,我这画一个站啊,咱们刚才不是说在应用程序类加载器里边,咱调这个叫load class,然后在这里边是不是调了一下你这个,诶parent就是扩展类加载器里这个叫load class,现在呢,咱们这个方法返回的是一个,就刚才说结束的时候是个no。再是个闹,是不是就意味着我们这块调完以后,这个C是个闹啊。就回到这儿来了啊,咱们刚才呢,是一个递归的一个操作,这是个no,这要是个no的话呢,是不是就放到这儿了,咱们现在呢,又回到第一开始的那个呃,Load class这个方法里了,相当于你现在在应用程序类加载器里边,那你这时候呢,就要呃调应用程序类加载器的这个叫find class的这个方法了。
14:14
是吧,哎,刚才我们说这个now呢,这不是两种场景,一种呢是这个时候呢,你这个类这块呢没加载,再一个呢,就是你要这块呢,就是引导类加载器,它没加载是吧?哎,第二这个find class,那针对于咱们这个应用程序类加载器呢,它是要加载的,哎,所以它调了一个find class呢,就获取了一个实打实的一个大的class的一个实例,然后把它呢做了一个返回。诶,那通过刚才呢,我们主要看这块这个逻辑啊,就是我们当一个类的加载器进行加载的话呢,它先找它的parent去做一个加载,那parent里边呢,再进来还有parent再去加载,所以可见呢,我们这儿呢,就是满足双亲委派机制的这个主要逻辑就在咱们这个load class当中来实现的。啊,这呢,就是我们说这个load class里边的这样的一个核心的一个代码啊,大家呢,需要去熟悉的就是它啊。
我来说两句