什么是类加载器?什么是双亲委派模型?

在这里插入图片描述

  1. 什么是类加载器,类加载器有哪些?
    要想理解类加载器的话,务必要先清楚对于一个Java文件,它从编译到执行的整个过程。在这里插入图片描述
    类加载器:用于装载字节码文件(.class文件)
    运行时数据区:用于分配存储空间
    执行引擎:执行字节码文件或本地方法
    垃圾回收器:用于对JVM中的垃圾内容进行回收
    1.1. 类加载器
    JVM只会运行二进制文件,而类加载器(ClassLoader)的主要作用就是将字节码文件加载到JVM中,从而让Java程序能够启动起来。现有的类加载器基本上都是java.lang.ClassLoader的子类,该类的只要职责就是用于将指定的类找到或生成对应的字节码文件,同时类加载器还会负责加载程序所需要的资源

1.2. 类加载器种类
类加载器根据各自加载范围的不同,划分为四种类加载器:

启动类加载器(BootStrap ClassLoader):

该类并不继承ClassLoader类,其是由C++编写实现。用于加载JAVA_HOME/jre/lib目录下的类库。

扩展类加载器(ExtClassLoader):

该类是ClassLoader的子类,主要加载JAVA_HOME/jre/lib/ext目录中的类库。

应用类加载器(AppClassLoader):

该类是ClassLoader的子类,主要用于加载classPath下的类,也就是加载开发者自己编写的Java类。

自定义类加载器:

开发者自定义类继承ClassLoader,实现自定义类加载规则。

上述三种类加载器的层次结构如下如下:
在这里插入图片描述
类加载器的体系并不是“继承”体系,而是委派体系,类加载器首先会到自己的parent中查找类或者资源,如果找不到才会到自己本地查找。类加载器的委托行为动机是为了避免相同的类被加载多次。

  1. 什么是双亲委派模型?
    如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类,而是把这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以完成类加载任务,就返回成功;只有父类加载器无法完成此加载任务时,才由下一级去加载。
    在这里插入图片描述
  2. JVM为什么采用双亲委派机制
    通过双亲委派机制可以避免某一个类被重复加载,当父类已经加载后则无需重复加载,保证唯一性。

为了安全,保证类库API不会被修改

在工程中新建java.lang包,接着在该包下新建String类,并定义main函数

public class String {public static void main(String[] args) {System.out.println("demo info");}
}

此时执行main函数,会出现异常,在类 java.lang.String 中找不到 main 方法
在这里插入图片描述
出现该信息是因为由双亲委派的机制,java.lang.String的在启动类加载器(Bootstrap classLoader)得到加载,因为在核心jre库中有其相同名字的类文件,但该类中并没有main方法。这样就能防止恶意篡改核心API库。

  1. 类装载的执行过程?
    类从加载到虚拟机中开始,直到卸载为止,它的整个生命周期包括了:加载、验证、准备、解析、初始化、使用和卸载这7个阶段。其中,验证、准备和解析这三个部分统称为连接(linking)。
    在这里插入图片描述
    类加载过程详解

1.加载
在这里插入图片描述
通过类的全名,获取类的二进制数据流。

解析类的二进制数据流为方法区内的数据结构(Java类模型)

创建java.lang.Class类的实例,表示该类型。作为方法区这个类的各种数据的访问入口
在这里插入图片描述
2.验证
在这里插入图片描述
验证类是否符合JVM规范,安全性检查

(1)文件格式验证:是否符合Class文件的规范

(2)元数据验证

这个类是否有父类(除了Object这个类之外,其余的类都应该有父类)

这个类是否继承(extends)了被final修饰过的类(被final修饰过的类表示类不能被继承)

类中的字段、方法是否与父类产生矛盾。(被final修饰过的方法或字段是不能覆盖的)

(3)字节码验证- 主要的目的是通过对数据流和控制流的分析,确定程序语义是合法的、符合逻辑的。

(4)符号引用验证:符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量

比如:int i = 3; 字面量:3 符号引用:i

3.准备
在这里插入图片描述
为类变量分配内存并设置类变量初始值

static变量,分配空间在准备阶段完成(设置默认值),赋值在初始化阶段完成

static变量是final的基本类型,以及字符串常量,值已确定,赋值在准备阶段完成

static变量是final的引用类型,那么赋值也会在初始化阶段完成
在这里插入图片描述
4.解析
在这里插入图片描述
把类中的符号引用转换为直接引用

比如:方法中调用了其他方法,方法名可以理解为符号引用,而直接引用就是使用指针直接指向方法。
在这里插入图片描述
5.初始化
在这里插入图片描述
对类的静态变量,静态代码块执行初始化操作

如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类。

如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。

6.使用
在这里插入图片描述
JVM 开始从入口方法开始执行用户的程序代码

调用静态类成员信息(比如:静态字段、静态方法)

使用new关键字为其创建对象实例

7.卸载

当用户程序代码执行完毕后,JVM 便开始销毁创建的 Class 对象,最后负责运行的 JVM 也退出内存

5.类加载器面试
面试官:什么是类加载器,类加载器有哪些?

候选人:

JVM只会运行二进制文件,而类加载器(ClassLoader)的主要作用就是将字节码文件加载到JVM中,从而让Java程序能够启动起来。

常见的类加载器有4个

第一个是启动类加载器(BootStrap ClassLoader):其是由C++编写实现。用于加载JAVA_HOME/jre/lib目录下的类库。

第二个是扩展类加载器(ExtClassLoader):该类是ClassLoader的子类,主要加载JAVA_HOME/jre/lib/ext目录中的类库。

第三个是应用类加载器(AppClassLoader):该类是ClassLoader的子类,主要用于加载classPath下的类,也就是加载开发者自己编写的Java类。

第四个是自定义类加载器:开发者自定义类继承ClassLoader,实现自定义类加载规则。

说一下类装载的执行过程?

类从加载到虚拟机中开始,直到卸载为止,它的整个生命周期包括了:加载、验证、准备、解析、初始化、使用和卸载这7个阶段。其中,验证、准备和解析这三个部分统称为连接(linking)

1.加载:查找和导入class文件

2.验证:保证加载类的准确性

3.准备:为类变量分配内存并设置类变量初始值

4.解析:把类中的符号引用转换为直接引用

5.初始化:对类的静态变量,静态代码块执行初始化操作

6.使用:JVM 开始从入口方法开始执行用户的程序代码

7.卸载:当用户程序代码执行完毕后,JVM 便开始销毁创建的 Class 对象,最后负责运行的 JVM 也退出内存

什么是双亲委派模型?

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

JVM为什么采用双亲委派机制

主要有两个原因。

第一、通过双亲委派机制可以避免某一个类被重复加载,当父类已经加载后则无需重复加载,保证唯一性。

第二、为了安全,保证类库API不会被修改

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/257022.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

V2X全方位通信部署产品支持智能交通建设!

来源:德思特测试测量丨德思特案例 | V2X全方位通信部署产品支持智能交通建设! 原文链接:https://mp.weixin.qq.com/s/Fhnvcq9HA60Sed5BIGcnSw 欢迎关注虹科,为您提供最新资讯! 01 案例背景 后疫情时代人们更注重于享…

USB总线驱动(二)设备驱动ch341以及serial

我们以一个usb设备(ch341)驱动例子来看下用法。 一、ch341设备驱动 如上,注册了一个ch341的驱动,根据指定的产品号和设备号,这个驱动将会适配3个类型的usb转串口设备。 module_usb_serial_driver最终转开成 标准的驱动…

正则表达式详细讲解

目录 一、正则表达式概念 二、八元素 1、普通字符: 2、元字符: 3、通配符 .: 4、字符类 []: 5、量词: 6、锚点 ^ 和 $: 7、捕获组 (): 8、转义字符 \: 三、日常使用的正则…

算法 最小生成树

算法选择 稠密图:朴素版普利姆算法【因为代码短】 稀疏图:克鲁斯卡尔算法【因为思路简单】 普利姆(Prim) 朴素 Prim 时间复杂度 O(n^2) 适用情况 稠密图 算法流程 集合:当前已经在连通块中的所有点 初始化距…

水平自动扩容和缩容HPA;API资源对象NetworkPolicy;Kubernetes用户安全控制;Kubernetes创建普通用户示例

水平自动扩容和缩容HPA;API资源对象NetworkPolicy;Kubernetes用户安全控制;Kubernetes创建普通用户示例 水平自动扩容和缩容HPA(本部分操作适合K8s版本>1.23.x) HPA全称是Horizontal Pod Autoscaler,翻译成中文是…

Windows 系统彻底卸载 SQL Server 通用方法

Windows 系统彻底卸载 SQL Server 通用方法 无论什么时候,SQL Server 的安装和卸载都是一件让我们头疼的事情。因为不管是 SQL Server 还是 MySQL 的数据库,当我们在使用数据库时因为未知原因出现问题,想要卸载重装时,如果数据库…

[LeetCode]-283. 移动零-1089. 复写零

目录 283. 移动零 描述 解析 代码 1089. 复写零 描述 解析 代码 283. 移动零 283. 移动零https://leetcode.cn/problems/move-zeroes/ 描述 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 &…

【Linux--基础IO】

目录 一、系统文件接口1.1 open1.2 write1.3 read1.4 close 二、文件描述符三、文件描述符的分配规则四、重定向4.1输出重定向的原理4.2dup2函数的系统调用 五、缓冲区5.1代码及现象5.2原理解释5.3C语言FILE 六、文件系统6.1磁盘的介绍6.1磁盘的分区管理 7、软硬连接7.1软连接7…

Windows本地如何添加域名映射?(修改hosts文件)

1. DNS(域名系统) Domain Name System(域名系统):为了加快定位IP地址的速度, 将域名映射进行层层缓存的系统. 目的:互联网通过IP(10.223.146.45)定位浏览器建立连接,但是我们不易区别IP,为了方便用户辨识I…

使用cmake构建的工程的编译方法

1、克隆项目工程 2、进入到工程目录 3、执行 mkdir build && cd build 4、执行 cmake .. 5、执行 make 执行以上步骤即可完成对cmake编写的工程进行编译 ,后面只需执行你的编译结果即可 $ git clone 你想要克隆的代码路径 $ cd 代码文件夹 $ mkdir bu…

【GAMES101】三维变换

games101的第四节课讲了三维变换和观察变换,我们这里先记录一下三维变换的知识,后面再讲观察变换 齐次坐标下的三维变换 类似于解决之前二维变换平移的问题,三维变换下用齐次坐标通过增加一个维度来表示,第四个维度为1表示这是个…

【计算机网络学习之路】HTTP请求

目录 前言 HTTP请求报文格式 一. 请求行 HTTP请求方法 GET和POST的区别 URL 二. 请求头 常见的Header 常见的额请求体数据类型 三. 请求体 结束语 前言 HTTP是应用层的一个协议。实际我们访问一个网页,都会像该网页的服务器发送HTTP请求,服务…