【JVM】JVM类的加载机制(详解)

JVM类的生命周期包括加载、验证、准备、解析和初始化等7个阶段,其中加载、验证、准备和解析是加载过程。加载时,JVM获取类的二进制字节流并创建class对象。验证确保字节流符合规范和Java语言要求。准备阶段为静态变量分配空间并赋初始值。解析将符号引用转换为直接引用。初始化执行类构造器方法。类加载遵循双亲委派机制,防止类重复加载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 类从加载到卸载,整个生命周期统共分为7个阶段:
    类生命周期
  • 其中,加载->验证->准备->解析->初始化,这5个过程就是类的加载过程,而且验证->准备->初始化这三个可以统称为连接过程;
  • 解析阶段有时候会在初始化之后再开始;

那么,什么时候会触发类的加载?

  • 1⃣️ main()所在的主类;
  • 2⃣️ 在遇到new、要对某个类的静态变量进行get或set、或者调用它的静态方法时;
  • 3⃣️ 对某个类使用反射时;
  • 4⃣️ 已经在对某个类进行加载,并且进行到初始化阶段时,而它的父类未加载时,JVM会先进行父类的加载,父类中也是一样的机制,层层递进,直到Object;
  • 5⃣️ 加载某个接口并进行到初始化时,且这个接口中使用了父接口(如引用父接口中定义的常量)时,触发对父接口的检查加载;

一、 加载

  • JVM根据类的全限定名获取类的二进制字节流;
  • 将其中静态数据结构转换成JVM内存中方法区中的数据结构;
  • 创建class对象,作为方法区中变量和方法的入口;

注: 这里不一定非要从一个Class文件中获取,既可以从ZIP(jar包)包中获取,也可以

二、 验证

目的:验证Class文件的字节流是否符合JVM的要求,且不会危害到JVM自身;

具体动作

  • 验证该字节流是否符合Class文件格式规范;
  • 验证数据类型和方法是否符合Java语言规范;
  • 验证符号引用是否都能找到对应的类;

三、准备

  • 给静态变量在方法区内分配空间,并赋上初始值;
  • 给非静态成员变量与在堆内分配空间,并赋初始值;

比如: public static int v=800;
准备阶段只会给v分配空间,并令v=0;

注: 1.整型赋0,浮点型赋0.0,char型赋’\u0000’,String赋null,boolean赋false

四、解析

  • 将常量池中的字面量和符号引用解析,换成直接引用;

符号引用是class文件中的:

  1. CONSTANT_Class_info
  2. CONSTANT_Field_info
  3. CONSTANT_Method_info
  • 符号引用:引用的目标不一定要已经加载到内存中;不同布局的虚拟机之间的符号引用必须是一致的,因为它们的字面量形式明确定义在了JVM规范的Class文件格式中;
  • 直接引用,是指向目标的指针,相对偏移量是一个能够间接定位到目标的句柄;直接引用代表着引用的目标一定已在内存中存在;

五、初始化

  • 是类加载过程的最后一步
  • 其实就是执行类构造器方法的过程,它是编译器从类中收集静态变量赋值操作和静态代码块的语句合并而成;
  • JVM会保证子类在执行<client>之前,父类的<client>已执行;
  • 引申:双亲委派机制

    • 类加载器
      启动类加载器(负责加载JAVA_HOME目录下类)、拓展类加载器(负责加载JAVA_HOME\lib\ext目录下类)、应用程序类加载器(负责加载用户路径classpath下类库)、自定义加载器(用户自定义类的加载器)
      在这里插入图片描述
    • 流程:当一个类收到类加载请求,他首先不会尝试自己去加载这个 类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的加载请求都会被传送到启动类加载器中,只有当父类加载器反馈自己在它的加载路径中没有找到所需加载的class时,才会向下反馈让子类加载器尝试加载;
    • 优点:这样能够保证类不会被重复加载——已经被父类加载过的类,子类不会再去加载;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值