当前位置: 首页 > article >正文

【JVM】类加载过程|双亲委派模型

 思维导图目录

四、类加载过程

1.类加载过程

2.双亲委派模型(经典面试题)

什么是双亲委派模型

双亲委派模型的优点

 破坏双亲委派模型


四、类加载过程

1.类加载过程

咱们写的java代码,是.java文件(硬盘),一个java进程要跑起来,就需要把.java先变成.class文件(硬盘),加载到内存中,得到“类对象”,其中就执行了指令,要执行的CPU指令,都是通过字节码(进入内存中)让JVM翻译出来的

从上⾯的图⽚我们可以看出整个JVM执⾏的流程中,和程序员关系最密切的就是类加载的过程了,所以接下来我们来看下类加载的执⾏流程。

对于⼀个类来说,它的⽣命周期是这样的:

类加载的几个环节(八股)

1.加载:在硬盘上,找到对应的.class文件,读取文件内容

2.验证:检查.class里的内容,是否符合要求

3.准备:给类对象,分配内存空间(元数据区)(类加载最终要得到的就是类对象),会把这个空间里的数据先全都填充为0(此时,如果这个类有静态成员,值就是0)

4.解析:针对字符串常量来初始化,把刚才.class文件中的常量的内容取出来,放到“元数据区”

5.初始化:针对类对象进行初始化(不是针对对象初始化,和构造方法无关),给静态成员进行初始化,执行静态代码块

此时类对象就搞定了

后续代码就可以使用这个类对象,创建实例,或者使用里面的静态成员了


2.双亲委派模型(经典面试题)

提到类加载机制,不得不提的⼀个概念就是“双亲委派模型”

站在Java虚拟机的⻆度来看,只存在两种不同的类加载器:⼀种是启动类加载器(Bootstrap  ClassLoader),这个类加载器使⽤C++语⾔实现,是虚拟机⾃⾝的⼀部分;另外⼀种就是其他所有的类加载器,这些类加载器都由Java语⾔实现,独⽴存在于虚拟机外部,并且全都继承⾃抽象类java.lang.ClassLoader。

站在Java开发⼈员的⻆度来看,类加载器就应当划分得更细致⼀些。⾃JDK 1.2以来,Java⼀直保持着三层类加载器、双亲委派的类加载架构器


什么是双亲委派模型

它出现在“加载”环节(第一步),根据代码中的写的“全限定类名”(包名+类名)找到对应的.class文件

这个模型描述了JVM加载.class文件过程中,找文件的过程

“类加载模型”在JVM中包含的一个特定的模块/类,这个类负责完成后续的类加载工作

JVM中内置了三个类加载器,负责加载不同的类

1)BootstrapClaaLoader (相当于爷爷)

负责加载标准库的类

2)ExtentionClassLoader(相当于父亲)

负责加载JVM扩展库的类

3)ApplicationClassLoader(相当于儿子)

负责加载第三方库的类自己写的代码的类

 此处的“父子关系”不是通过类的继承表示的(不是父类子类),而是通过类加载器中存在一个“parent”这样的字段,指向自己的父亲,类似于二叉树中的“三叉实现形式”)

“双亲委派模型”本身翻译是不准确的,更准确的翻译:“父亲委派模型”,“单亲委派模型”

工作过程举例:

给定一个类的全限定类名:java111.Test

此时加载过程如下:

(1)工作从ApplicationClassLoader开始进行

ApplicationClassLoader并不会立即搜索第三方库的相关目录,而是把任务交给自己的父亲来进行处理

(2)工作就到ExtentionClassLoader

ExtentionClassLoader也不会立即搜索负责的扩展库的目录,也是把任务交给自己的父亲来处理

(3)工作就来到BootstrapClaaLoader

BootstrapClaaLoader也像交给自己的父亲来处理,但是它的parent指向null,只能自己处理,BootstrapClaaLoader尝试在标准库的路径中搜索上述的类

(4)工作回到了ExtentionClassLoader

此时就要搜索扩展库对应的目录了

如果找到了,就由当前的类加载器负责打开文件,读取文件等后续操作...

如果找不到,任务就还是要继续还给儿子来处理

(5)工作回到了ApplicationClassLoader

此时要搜索第三方库/用户项目代码的目录了

如果找到了,也就是由当前的类加载器负责处理

如果没有找到,任务还是要继续还给儿子来处理

but,此时没有儿子了,还没找到,最早就会抛出一个ClassNotFoundException

本质就是:拿到任务,先交给父亲处理,父亲处理不了,在自己处理


双亲委派模型的优点

1. 避免重复加载类:⽐如A类和B类都有⼀个⽗类C类,那么当A启动时就会将C类加载起来,那么在B类进⾏加载时就不需要在重复加载C类了。

2. 安全性:使⽤双亲委派模型也可以保证了Java的核⼼API不被篡改,如果没有使⽤双亲委派模型,⽽是每个类加载器加载⾃⼰的话就会出现⼀些问题,⽐如我们编写⼀个称为java.lang.Object类的话,那么程序运⾏的时候,系统就会出现多个不同的Object类,⽽有些Object类⼜是⽤⼾⾃⼰提供的因此安全性就不能得到保证了(JVM会确保加载的类是标准库的类)


 破坏双亲委派模型

but 双亲委派模型虽然有其优点,但在某些情况下也存在⼀定的问题,⽐如Java中SPI(Service Provider Interface,服务提供接⼝)机制中的JDBC实现:

因为DriverManager位于rt.jar包,由BootStrap类加载器加载,⽽其Driver接⼝的实现类是位于服务商提供的Jar包中,是由⼦类加载器(线程上下⽂加载器 Thread.currentThread().getContextClassLoader)来加载的,这样就破坏了双亲委派模型了(双亲委派模型讲的是所有类都应该交给⽗类来加载,但JDBC显然并不能这样实现)


http://www.kler.cn/news/310842.html

相关文章:

  • RTX 4090 系列即将停产,RTX 5090 系列蓄势待发
  • 【系统架构设计】系统的可靠性分析与设计
  • 接口自动化框架入门(requests+pytest)
  • 最好用的翻译器:什么是DeepL?如何订阅支付DeepL,订阅DeepL Pro以及申请DeepL API?
  • 蓝桥杯—STM32G431RBT6按键的多方式使用(包含软件消抖方法精讲)从原理层面到实际应用(一)
  • TS - tsconfig.json 和 tsconfig.node.json 的关系,如何在TS 中使用 JS 不报错
  • 产品经理注意!11月NPDP考试预报名已开启
  • Oracle 11gR2打PSU补丁详细教程
  • 监控系列之-Grafana面板展示及制作
  • Flutter 优化技巧分享
  • Linux 内存分析工具 —— heaptrack
  • 代理IP批理检测工具,支持socks5,socks4,http和https代理批量检测是否可用
  • MySQL基础作业五
  • Text2SQL论文笔记 A Survey on Employing Large Language Models for Text-to-SQL Tasks
  • linux-L3-linux 复制文件
  • HBase在大数据实时处理中的角色
  • 【IEEEACM Fellow、CCF组委】第三届人工智能与智能信息处理国际学术会议(AIIIP 2024)
  • Python | Leetcode Python题解之第405题数字转换为十六进制数
  • java泛型的概念与好处
  • 【Git】常见命令(仅笔记)
  • Spark任务读取hive表数据导入es
  • 算法笔试-编程练习-好题-06
  • 【HarmonyOS NEXT】DevEco快速实现真机截屏,并保存到电脑
  • JVM面试真题总结(十一)
  • ORM框架详解:为什么不直接写SQL?
  • 软件渗透测试流程有哪些?专业软件测评公司简析渗透测试的好处
  • (k8s)Kubernetes 从0到1容器编排之旅
  • 使用blender快速制作metahuman面部以及身体绑定教程
  • 【C语言】分支和循环专题应用
  • QT<24> Qt和windows中获取CPU序列号号以及主板序列号