jvm|JVM笔记二双亲委派机制


jvm|JVM笔记二双亲委派机制
文章图片
jvm|JVM笔记二双亲委派机制
文章图片
JVM的双亲委派机制
JVM类加载器是什么机制?为什么使用这种机制(这种机制的好处是什么)?说下类加载流程?用代码验证类加载机制 。 为什么要破坏类的这种加载机制?
JVM笔记二双亲委派机制
JVM双亲委派机制 , 简单来说:我爸是李刚 , 有事找我爸 。 用三个字来说:往上捅 。 不信?咱们一起看看
我们已经知道了JVM类加载器的四种加载机制 , 那么这四种加载机制是怎么个加载过程呢?我们再来看看类加载器的图例:
图一:双亲委派机制图例
先来看看类和类加载器:
类和类加载器对于任意一个类 , 都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性 。 当我们比较两个类是否相等的时候 , 前提是:只有在这两个类是由同一个类加载器加载为前提下才有意义的 。
通过上面文字描述 , 我们知道了 , 在JVM中 , 类可以通过不同类加载器加载的 。 这个信息很重要 。 既然类可以通过不同加载器加载后 , 使其不与其他类equals 。 那么 , 是否可以自己写个java.lang.string类呢?我们都知道 , 自己写的类是appClassLoader加载到JVM的;jvm原生的string类是由bootstrapClassLoader加载的 。 这两个类是不同的加载器加载 , 是不eqs的 。 那么实际上可以吗?答案是:不可以(下文凯哥Java(wxID:kaigejava)会通过代码来证实) 。 为什么不可以呢?因为双亲委派机制的缘故 。
双亲委派机制如果从JVM角度来讲的话 , 类的加载器只有两种:启动类加载器 。 这个类是C++写的 , 是JVM虚拟机自身的一部分;另一种就是所有其他类的类加载器了 。 是Java写的 , \t独立于虚拟机外部的 , 而且都是继承于:java.lang.ClassLoader的 。
从我们Java开发任意角度来看的话 , 就可以分为四种类加载器了 。 这里先不具体概述了 , 在下文会介绍的 。
在图一的图例中展示的类加载器之间层次管理 , 就被称之为双亲委派模型(Parents Delegation Model) 。
双亲委派机制药圈 , 除了顶层的类加载器(Bootstrap)外 , 其余的类加载器都应该有自己的父类加载器 。 PS:通过上一篇《JVM学习笔记之类装载器-ClassLoader》的最后 , 我们通过代码演示了 , 自定义类的父加载器是appClassLoaderappClassLoader的父加载器是扩展类加载器 。
双亲委派机制的执行过程:
如果一个类加载器收到了类加载的请求 , 这个类加载器不会先尝试加载这个类 , 而是会先把这个请求委派给自己的父类加载器去完成 , 在每个层次的类加载器都是依此类推的 。 因此所有的类加载器请求其最后都应该被委派到顶层的启动类加载器中(Bootstrap) , 只有当父类的加载器在自己管辖范围内(文末会介绍每个类加载器管理范围的)没有找到所需要的类的时候 , 子类加载器才会尝试自己去加载的 , 如果自己管理范围内也找不到需要加载的就会抛出:ClassNotFoundException 这个异常了 。 这就是为什么如果我们自己写java.lang.string类的时候 , 是不行的 。
我们可以自己尝试着创建一个java.lang.String类 , 类里面只有一个main方法 , 执行会是什么样的呢?
如上图:运行的时候 , 报错了 。 根据提示 , 我们就能知道 , 自己写的string类在启动的时候 , 类加载了 , 向上父类委派 , 最终委派到启动类加载器了 , 启动了加载器发现自己管辖的范围内存在String类 , 然后调用Main方法的时候 , 发现没有这个方法 , 就报错了 。 这个流程执行的简图: