2.双亲委派机制详细解析及原理 (5)

我们知道, 这肯定是没有的了. 然后继续判断, ExtClassLoader的parent是否为空. 很显然, 他就是空啊, 因为ExtClassLoader的父类加载器是引导类加载器BootStrapClassLoader, 而引导类加载器是c++写的,所以,这里的parent为空. parent为空执行的是else中的代码

3.从BootStrapClassLoader中查找

2.双亲委派机制详细解析及原理

这个方法就是去引导类加载器BootstrapClassLoad中查找, 是否有这个类, 我们来看看引导类加载器里面的具体实现

2.双亲委派机制详细解析及原理

我们发现, 最后具体的逻辑也是一个本地方法实现的. 我们还是猜测一下, 这就是去查找引导类加载器已经加载的类中有没有com.lxl.jvm.Math, 如果有就返回这个类, 如果没有就返回null.

很显然, 是没有的. c == null. 我们继续来看下面的代码

到此为止, 我们第一次向上查找的过程就完完事了. 用图表示就是这样

2.双亲委派机制详细解析及原理

首先有应用程序类加载器加载类, 判断应用程序已加载的类中, 是否有这个类, 结果是没有, 没有则调用其父类加载器ExtClassLoader的loadClass()方法, 去扩展类加载器中查找是否有这个类, 也没有. 那么判断其父类是否为空, 确实为空, 则进入到引导类加载器中取查找是否有这个类, 最后引导类加载器中也没有, 返回null

2.2 类加载器向下委派加载

下面来看看类加载器是如何向下委派的?

1.启动类加载器加载目标类

引导类加载器中也没有这个类, 返回null, 这里的返回空包含了两个步骤,一个是查找,没找到,二是没找到后去/lib/jar目录下加载这个类,也没有加载到。最后返回null。然后回到ExtClassLoader.loadClass(...).

2.扩展类加载器加载目标类

接下来调用findClass(name);查找ExtClassLoader中是否有com.lxl.jvm.Math, 我们来看看具体的实现. 首先这是谁的方法呢?是ExtClassLoader的.

2.双亲委派机制详细解析及原理

进入到findClass(name)方法中, 首先看看ExtClassLoader类中是否有这个方法, 没有, 这里调用的是父类UrlClassLoader中的findClass()方法

2.双亲委派机制详细解析及原理

在findClass()里面, 我们看到将路径中的.替换为/,并在后面增加了.class. 这是在干什么呢? 是将com.lxl.jvm.Math替换为com/lxl/jvm/Math.class,这就是类路径

然后去resource库中查找是否有这个路径. 没有就返回null, 有就进入到defineClass()方法.

我们想一想, 在ExtClassLoader类路径里面能找到这个类么?显然是找不到的, 因为这个类使我们自己定义的.

他们他一定执行return null.

2.双亲委派机制详细解析及原理

正如我们分析, debug到了return null; 这时执行的ExtClassLoader的findClass(). 返回null, 回到AppClassLoader加载类里面

3.应用程序类加载器加载目标类

2.双亲委派机制详细解析及原理

c就是null, 然后继续执行findClass(name), 这时还是进入到了URLClassPath类的findClass(name)

2.双亲委派机制详细解析及原理

如上图, 此时调用的是AppClassLoader的findClass(name), 此时的resource还是空么?当然不是了, 在target目录中就有Math.class类, 找到了, 接下来执行defineClass(name,res)

defindClass这个方法是干什么的呢? 这个方法就是加载类. 类已经找到了, 接下来要做的就是将其加载进来了.

类加载的四个步骤

defindClass()这个类执行的就是类加载的过程。 也就是下图中的四个步骤:验证->准备->解析->初始化。如下图红线圈出的部分.

2.双亲委派机制详细解析及原理

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgjzpz.html