JVM类加载机制

JVM类加载机制

关于JVM的类加载机制,可以理解为:把编译完成的 .class文件,从文件硬盘加载到内存中(元数据区)这样的一个过程,最终要获取到类对象。这个过程,可以大致理解为以下几个步骤:

加载:把 .class 文件找到,打开文件,读文件,把文件内容读到内存中;

验证:检查 .class 文件格式对不对,.class文件是一个二进制文件,此处的检查是根据官方提供的 JVM 虚拟机规范,它会说明描述 .class 的规范;

准备:给类对象分配内存空间(在元数据区占用一个空间) ,内存初始化成全0,为类中定义的静态变量分配内存,并设置初始值也为0;

解析: 初始化字符串常量,把符号引用转成直接引用;

符号引用转成直接引用:对于字符串常量来说,是需要有一块内存空间,来存这个字符的实际内容的,还需要有一个引用,来保存这个内存空间的起始地址,而在类加载过程中,字符串常量是存储在 .class 文件中的,而不是内存上的,此时的这个 "引用" 记录的不是字符串常量的真正地址,而是它在文件中的一个偏移量,这个偏移量就理解为 "符号引用";

在类加载之后,才真正的把这个字符串常量放在内存中,此时才是真正拥有内存地址,此时的内存地址就理解为 "直接引用" ;

初始化: 针对类对象里面的内容进行初始化,加载父类,执行父类静态代码块,父类静态变量赋值,子类静态代码块,子类静态变量赋值,父类初始化模块,父类普通变量,父类构造器,子类初始化模块,子类普通变量,子类构造器...

一个类什么时候会被加载呢?

并不是Java程序一运行,就把所有的类都加载了,而是等到了真正用到的时候,才会去加载,属于是懒汉模式,一般会有以下三种情况:

  1. 构造类的实例;
  2. 调用了这个类的静态方法,或者使用到了这个类的静态属性;
  3. 加载子类的时候,通常会先加载其父类;
    一般是用到了才会进行类加载,并且加载过一次后,后续再使用也不需要进行重复加载了;
    双亲委派模型

双亲委派模型,描述的是JVM类加载机制中的 加载 过程,也就是找 .class 文件的过程;

JVM 默认提供了三个类加载器:

  1. BootstrapClassLoader:负责加载标准库中的类;
  2. ExtensionClassLoader:负责加载 JVM 扩展库中的类;
  3. ApplicationClassLoader: 负责加载用户提供的,也就是用户代码中的类;
    在这三个类加载器中,存在一个 "父子关系" --- 每个 ClassLoader 类中会有一个 parent 属性来标识自己的父加载器:
    ApplicationClassLoader 的 parent 是 ExtensionClassLoader;
    ExtensionClassLoader 的 parent 是 BootstrapClassLoader;
    类加载器的加载过程

当加载一个类的时候,是从 ApplicationClassLoader 开始的,但它会把当前的加载任务交给父亲去做,也就是让 ExtensionClassLoader 去加载,然后 ExtensionClassLoader 也把任务交给父加载器,也就是 BootstrapClassLoader 去加载,此时 BootstrapClassLoader 的 parent 是 null 了,也就只能自己去加载,此时 BootstrapClassLoader 就要搜索自己负责的标准库中的类,如果能找到,就加载,如果找不到,就再返回交给 ExtensionClassLoader 去加载,同样的道理,如果 ExtensionClassLoader 在自己负责的 JVM 扩展库中找到了对应的类,就加载,如果找不到,就再返回给 ApplicationClassLoader 去加载,如果找到了就加载,如果到最后都没有找到,那么就会抛出 类找不到 这样的一个异常;

就大致是一个这样的执行过程:

之所以以这样的一个加载顺序,让标准库先加载,然后再扩展库,最后再是用户写的类,是为了防止用户可能会写出一些标准库或者扩展库已经存在的类的,就比如 java.lang.String,而这个是标准库中已经存在的类的,按照上述的加载顺序,JVM 最后加载出来的就是标准库中的类,而不是用户自己写的;

另一方面,类加载器也是可以自定义的,以上三个是 JVM 自带的,用户自定义的类加载器,也可以加入到上述的流程中使用,自己写的类加载器,可以遵守双亲委派模型,也可以选择不遵守,例如 Tomcat,去加载 webapp 这里就是单独的类加载器,不遵守双亲委派模型;

相关推荐
机智的叉烧1 分钟前
前沿重器[57] | sigir24:大模型推荐系统的文本ID对齐学习
人工智能·学习·机器学习
路在脚下@30 分钟前
spring boot的配置文件属性注入到类的静态属性
java·spring boot·sql
啦啦右一32 分钟前
Spring Boot | (一)Spring开发环境构建
spring boot·后端·spring
森屿Serien33 分钟前
Spring Boot常用注解
java·spring boot·后端
量子-Alex1 小时前
【多模态聚类】用于无标记视频自监督学习的多模态聚类网络
学习·音视频·聚类
吉大一菜鸡1 小时前
FPGA学习(基于小梅哥Xilinx FPGA)学习笔记
笔记·学习·fpga开发
苹果醋32 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
Hello.Reader2 小时前
深入解析 Apache APISIX
java·apache
盛派网络小助手2 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#
菠萝蚊鸭2 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel