JVM(七)--双亲委派模型

JVM(七)–双亲委派模型

类加载器:

虚拟机设计团队把类的加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”。

什么是类加载器?简答的说,就是根据指定的全限定名将class文件加载到jvm内存,转为Class对象。(将类信息通过类装载器(ClassLoader)加载并初始化生成Class模板放入运行时数据区(方法区)中

类装载器ClassLoader:负责加载class文件(存在于硬盘上),class文件在文件开头有特定的文件标识(表示我是一个class文件,我将被类加载器加载到内存中),将class文件字节码内容加载到内存中(jvm),并将这些内容转换成方法区中的运行时数据结构并且classloader只负责class文件的加载,至于其是否可以运行,则由Execution Engine决定

在这里插入图片描述

对上图的解释:

  • ①Class File(这里为Car.class)存在于本地硬盘上,可以理解为设计师画在纸上的模板,而最终这个模板在执行的时候是要加载到jvm当中来根据这个文件实例化出几个一模一样的实例.
  • ②Class file加载到jvm中,被称为DNA元数据模板,放到方法区中
  • ③在.class文件->JVM–>最终成为元数据模板,此过程就要一个运输工具(类装载器ClassLoader),扮演一个快递员角色。

对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性。这句话表达得更通俗一些就是:比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载地前提下才有意义,否则,即使这两个类来源于同一个class文件,但是加载它们地类加载器不同,那这两个类就必定不相等

==>不管别的,只要加载这2个类的类加载器不同,那么这2个类必定不相等

双亲委派模型:

站在Java虚拟机的角度,只存在两种不同地类加载器一种是启动类加载器,这个类加载器使用C++语言实现,是虚拟机自身的一部分;另一种是所有其他的类加载器,这个类加载器都由Java语言实现,独立于虚拟机外部,并且全部继承自抽象类java.lang.ClassLoader

从Java开发人员的角度来看,类加载器就还可以划分得更细致一些,绝大部分Java程序都会使用到一下三种系统提供的类加载器:(这三种类加载器一般是相互配合进行加载的,如果有必要,还可以加入自己定义的类加载器)

  • 启动类加载器:这个类加载器负责将存放在<JAVA_HOME>\lib目录中,或者被-Xboootclasspath参数所指定的路径中的,并且是虚拟机识别类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用
  • 扩展类加载器:这个加载器由sum.misc.Launcher$ExtClassLoader实现,它负责加载<JAVA_HONE>\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器
  • 应用程序类加载器:这个类加载器由sum.misc.Launcher$AppClassLoader来实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。它负责加载用户类路径上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器

在这里插入图片描述
图中展示的类加载器之间的这种层次关系,就称为类加载器的双亲委派模型。双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。

双亲委派模型的工作原理:

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父亲加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当附加在其反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载

为什么使用双亲委派模型:

使用双亲委派模型来组织类加载器之间的关系,有一个显而易见的好处Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己写一个名为java.lang.Object的类,并放在程序的ClassPath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无从保证,应用程序也将会变得一片混乱。

注意的点: 类加载器负责加载所有的类,系统为所有被载入内存中的类生成一个java.lang.class实例。一旦一个类配载入JVM中,同一个类不能被再次加载了。

  • 在JVM中标识两个Class对象,是否是同一个对象存在的两个必要条件
  • 类的完整类名必须一致,包括包名。
  • 加载这个ClassLoader(指ClassLoader实例对象)必须相同。

沙箱机制:

沙箱机制是基于双亲委派机制上采取的一种jvm自我保护机制。假设你要写一个java.lang.String类,由于双亲委派机制的原因,此请求会先交给启动类加载器试图进行加载,但是启动类加载器首先通过包+类名查找rt.jar中有没有该类,有则优先加载rt.jar包中的类,因此,就保证了java的运行机制不会被破坏

附上一个相关的链接:
https://mp.weixin.qq.com/s/9b_dMVk1ZFuB5kSlpgkckQ

感谢并参考:

https://blog.csdn.net/xiaojie_570/article/details/80390649
https://blog.csdn.net/qfc8930858/article/details/89762529

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值