面试笔记——类加载器

发布于:2024-05-07 ⋅ 阅读:(34) ⋅ 点赞:(0)

基础

在这里插入图片描述

  • 类加载器:用于装载字节码文件(.class文件)
  • 运行时数据区:用于分配存储空间
  • 执行引擎:执行字节码文件或本地方法
  • 垃圾回收器:用于对JVM中的垃圾内容进行回收

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

类加载器分类:
在这里插入图片描述

  • 启动类加载器(BootStrap ClassLoader):加载JAVA_HOME/jre/lib目录下的库。
  • 扩展类加载器(ExtClassLoader):主要加载JAVA_HOME/jre/lib/ext目录中的类。
  • 应用类加载器(AppClassLoader):用于加载classPath下的类。
  • 自定义类加载器(CustomizeClassLoader):自定义类继承ClassLoader,实现自定义类加载规则。

双亲委派模型

加载某一个类,先委托上一级的加载器进行加载,如果上级加载器也有上级,则会继续向上委托,如果该类委托上级没有被加载,子加载器尝试加载该类。

使用双亲委派机制的作用:

  • 通过双亲委派机制可以避免某一个类被重复加载,当父类已经加载后则无需重复加载,保证唯一性。
  • 为了安全,保证类库API不会被修改。

举例:
在这里插入图片描述

类装载的执行过程

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

  • 通过类的全名,获取类的二进制数据流。
  • 解析类的二进制数据流为方法区内(元空间)的数据结构(Java类模型) 。
  • 创建java.lang.Class类的实例(堆),表示该类型。作为方法区这个类的各种数据的访问入口 。

如图:
在这里插入图片描述
验证: 验证类是否符合 JVM规范,安全性检查
主要验证以下4项:
(1)文件格式验证
(2)元数据验证
(3)字节码验证
(4)符号引用验证——Class文件在其常量池会通过字符串记录自己将要使用的其他类或者方法,检查它们是否存在,如图:
在这里插入图片描述

其中,前三项都是格式检查,如——文件格式是否错误、语法是否错误、字节码是否合规。

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

  • static变量,分配空间在准备阶段完成(设置默认值),赋值在初始化阶段完成
  • static变量是final的基本类型,以及字符串常量,值已确定,赋值在准备阶段完成
  • static变量是final的引用类型,那么赋值也会在初始化阶段完成

解析: 把类中的符号引用转换为直接引用。
比如:方法中调用了其他方法,方法名可以理解为符号引用,而直接引用就是使用指针直接指向方法。
在这里插入图片描述

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

  • 如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类。
  • 如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。
  • 如果子类访问父类静态变量,只触发父类初始化。

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

  • 调用静态类成员信息(比如:静态字段、静态方法)
  • 使用new关键字为其创建对象实例

综上,类装载构成为:

  • 加载:查找和导入class文件
  • 验证:保证加载类的准确性
  • 准备:为类变量分配内存并设置类变量初始值
  • 解析:把类中的符号引用转换为直接引用
  • 初始化:对类的静态变量,静态代码块执行初始化操作
  • 使用:JVM 开始从入口方法开始执行用户的程序代码
  • 卸载:当用户程序代码执行完毕后,JVM便开始销毁创建的Class对象。