【JVM】类加载机制

Class 文件结构

Java 字节码文件主要包括以下几部分:

  • 魔数与class 文件的版本
  • 常量池
  • 访问标志:表示该 class 的属性和访问类型,该 class 是类还是接口,是不是 public,是否被 final 修饰
  • 类索引、父类索引、接口索引
  • 字段表属性:用于描述接口或类中描述的变量。比如变量的作用域(public、peivate),是否是静态变量(static),可变性(final),数据类型(基本类型、对象、数组)等等
  • 方法表属性:和字段表类似,描述的是方法的属性
  • 属性表属性:用于描述某些特定场景专有的信息

常量池

常量池主要存放两大类:字面量和符号引用。字面量类似于Java的常量的概念,如文本字符串,final常量等。符号引用包括以下三种:

  • 类和接口的全限定名
  • 变量的名称和描述符号
  • 方法的名称和描述符
    JVM 是在类加载阶段才开始进行动态链接的,也就是说这些字段和符号引用只有在运行期转换后才能获取真正的内存入口地址

Java 类加载机制

类加载主要分为三个阶段:加载、连接和初始化;连接阶段又可分为:验证、准备和解析

加载阶段:查找并加载类的二进制数据

加载阶段主做三件事情:

  • 通过类的全限定名来获取类的二进制字节流
  • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
  • 在 Java 堆中生成一个 java.lang.class 对象,作为对方法区中这些数据的访问入口
    加载阶段总结:查找并加载类的二进制数据,并在 JVM 堆中创建一个 class 对象,并且将类的信息保存至方法区

连接阶段

验证:验证是否符合 Java 规范和 JVM 的规范

验证阶段主要进行的是对文件格式的验证、元数据验证、字节码验证和符号引用验证

准备:为类的静态变量分配内存,并初始化为默认值

准备阶段正式为变量分配内存并设置变量的初始值,这些内存都是在方法区中分配的。

  • 在准备阶段进行内存分配的只有类变量(static),实例变量会在对象实例化时随着对象在堆中一起分配内存
  • 在准备阶段为变量赋的初始值都是默认值(0, null, 0L, false)
解析:把类中的符号引用转换为直接引用

解析阶段是虚拟机将常量池内符号引用转换为直接引用的过程,符号引用包括类和接口的全限定名、变量的名称和描述符号、方法的名称和描述符。直接引用就是指向目标的指针。

初始化:为静态变量赋予正确的初始值

初始化阶段主要就是为静态变量赋予初始值

初始化时机:

  • 使用 new 创建类的实例
  • 访问类或接口的静态变量或对静态变量赋值
  • 访问类的静态方法
  • 反射
  • 初始化某个子类其父类也会初始化
  • 启动类

类加载器 类加载机制

类加载器

BootStrapClassLoader -> ExtClassLoader -> AppClassLoader -> User ClassLoader

类加载机制:双亲委派机制

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。

  1. 当 AppClassLoader 要加载一个 class 时,他首先不会自己尝试去加载这个类,而是将加载类的任务委托给父类 ExtClassLoader 去完成
  2. 当 ExtClassLoader 要加载一个 class 时,他首先不会自己尝试加载这个类,而是把类加载请求委托给 BootStrapClassLoader 去完成
  3. 如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;
  4. 若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException。
相关推荐
计算机就业还在扩大5 分钟前
第2期-cmp.Ordered+类型推断+刻意未支持的特性
后端·面试·golang
指剑18 分钟前
亚麻云之EC2——安全组与密钥对:SSH 端口怎么开才安全,Permission denied (publickey) 和连接超时排查
java·安全·ssh
_Evan_Yao8 小时前
Redis 缓存穿透、击穿、雪崩,一次讲清!
java·spring·mybatis
梓豪csd8 小时前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
秋饼8 小时前
Spring AI 2.1 Message Parts 深度实战:推理签名回放与跨轮记忆持久化的源码级落地
java·ai·技术分享·后端开发
王中阳Go9 小时前
两个入口答案不一致先别调模型:6 行入口口径对账表(附脚本)
人工智能·后端·python·大语言模型·1024程序员节
thefool1122669 小时前
TCP 1
java·1024程序员节
码事漫谈10 小时前
消除AI幻觉,普通人能做的五件事
后端
金銀銅鐵12 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
AI人工智能+电脑小能手12 小时前
一次请求打几个下游,这个Java并行任务工具类6个方法按序聚合
java·线程池·并发编程·1024程序员节·批量处理·并行任务