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

相关推荐
JavaNice哥19 分钟前
1初识别jvm
jvm
涛粒子19 分钟前
JVM垃圾回收详解
jvm
YUJIANYUE22 分钟前
PHP将指定文件夹下多csv文件[即多表]导入到sqlite单文件
jvm·sqlite·php
逊嘘31 分钟前
【Java语言】抽象类与接口
java·开发语言·jvm
鱼跃鹰飞10 小时前
大厂面试真题-简单说说线程池接到新任务之后的操作流程
java·jvm·面试
王佑辉11 小时前
【jvm】Major GC
jvm
阿维的博客日记11 小时前
jvm学习笔记-轻量级锁内存模型
jvm·cas·轻量级锁
曹申阳14 小时前
2. JVM的架构模型和生命周期
jvm·架构
琪露诺大湿15 小时前
JavaEE-多线程初阶(4)
java·开发语言·jvm·java-ee·基础·1024程序员节·原神
王佑辉17 小时前
【jvm】Full GC
jvm