JVM(类加载机制)

类加载就是 .class 文件, 从文件(硬盘) 被加载到内存(元数据区)中的过程


类加载的过程

加载: 找 .class 文件的过程, 打开文件, 读文件, 把文件读到内存中
验证: 检查 .class 文件的格式是否正确

  • .class 是一个二进制文件, 其格式有严格的说明
    准备: 给类对象分配内存空间 (先在元数据区占个位置), 也会使静态成员被设置成 0 值
    解析: 初始化字符串常量, 把符号引用转换为直接引用

  • 字符串常量,有一块内存空间存放其实际内容, 还有一个引用,来保存这块内存空间的起始地址

  • 在类加载之前,字符串常量处在 .class 文件中, 此时这个 引用 记录的并非是字符串常量的真正地址, 而是它在文件中的 "偏移量" (或者说是占位符)

  • 类加载之后, 才真正把这个字符串常量给放到内存中, 此时才有 "内存地址",该引用才能被真正赋值成指定的内存地址
    初始化: 调用构造方法, 进行成员初始化, 执行代码块, 静态代码块, 加载父类 ...

顺便看一下类的生命周期


一个类加载的时机(一个类何时会被加载)

JVM 采用的是懒汉模式
1.构造类的实例

2.调用该类的静态方法 / 使用静态属性

3.加载子类的时候, 会先加载其父类
即用到了, 才加载, 加载过后, 后续使用不必重复加载


双亲委派模型

上述类加载过程中有个环节 ---- 加载 : 找到 .class 文件, 并读取到内存中
双亲委派模型,描述的就是该过程

JVM 提供了三个类加载器

BootstapClassLoader : 负责加载 标准库 中的类, Java 规范要求提供的类(即所有 JVM 都会提供的)

ExtensionClassLoader : 负责加载 JVM 拓展类 中的类, 规范之外, JVM 厂商 / 组织提供的额外的功能

ApplicationClassLoader : 负责加载 用户提供的第三方库 / 用户项目代码 中的类
上述三个类加载器存在 "父子关系", 即每个类加载器中有一个 parent 属性指向自己的 父 类加载器

上述类加载器如何配合工作?(双亲委派模型的流程)

简单版本:

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父

类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最 终都应该传送到最顶层的启

动类加载器中,只有当父加载器反馈自己无 法完成这个加载请求(它的搜索范围中没有找到所需的类)

时,子加载器才会尝试自己去完成加载。
详细版本:

当加载一个类的时候, 先从 ApplicationClassLoader 开始

但是 ApplicationClassLoader 不会直接加载, 而是会把任务交给自己的父亲,让父亲去完成

于是 ExtensionClassLoader 就去加载了, 但是 ExtensionClassLoader 也不是直接加载, 而是再委托给自己的父亲去加载

现在 BootstrapClassLoader 就要去加载了, 在此之前, BootstrapClassLoader 也会先委派给自己的父亲, 此时会发现, 自己的父亲是 null

即 BootstrapClassLoader 并没有父亲

  • 没有父亲或者父亲加载完了,没有找到类, 这两种情况下才会由自己加载

此时 BootstrapClassLoader 会加载该类, 即搜索自己负责的标准库目录里的相关类, 如果找到, 就加载, 找不到,则由子类加载器进行加载

ExtensionClassLoader 搜索拓展库相关目录, 如果找到就加载, 找不到就由子类加载器进行加载

ApplicationClassLoader 搜索用户项目相关目录, 如果找到就加载, 找不到就由子类加载器进行加载 (由于 ApplicationClassLoader 没有子加载器, 会抛出异常 ---- 类找不到)

双亲委派模型的目的

保证 Bootstrap 能够先加载类, Appcation 能够后加载类

放在当用户自定义的类和标准库中类同名时, 能够优先使用标准库中的类(防止不必要的 bug)

双亲委派模型的优点(其实就是上面目的的另一种说法)

  1. 避免重复加载类
  2. 安全性: 使用双亲委派模型保证 Java 的核心 API 不被篡改

破坏双亲委派模型

很好的一个示例是 JDBC

其中 Driver 接口的实现类是由 子类加载器加载的 (我自己包里的类肯定是要用的, 如果遵循双亲委派模型, 那我不是白写了 [用不到] )
综上, 是否遵循双亲委派模型可以根据需求具体修改

相关推荐
1.01^100020 小时前
[5-01-01].第04节:初识字节码文件 - 字节码文件作用
jvm
找不到、了1 天前
JVM核心知识整理《1》
jvm
L.EscaRC1 天前
面向 Spring Boot 的 JVM 深度解析
jvm·spring boot·后端
学到头秃的suhian2 天前
JVM-类加载机制
java·jvm
NEFU AB-IN2 天前
Prompt Gen Desktop 管理和迭代你的 Prompt!
java·jvm·prompt
唐古乌梁海2 天前
【Java】JVM 内存区域划分
java·开发语言·jvm
众俗2 天前
JVM整理
jvm
echoyu.2 天前
java源代码、字节码、jvm、jit、aot的关系
java·开发语言·jvm·八股
代码栈上的思考3 天前
JVM中内存管理的策略
java·jvm
thginWalker3 天前
深入浅出 Java 虚拟机之进阶部分
jvm