8. JVM类装载的执行过程

1. JVM介绍和运行流程-CSDN博客

2. 什么是程序计数器-CSDN博客

3. java 堆和 JVM 内存结构-CSDN博客

4. 虚拟机栈-CSDN博客

5. JVM 的方法区-CSDN博客

6. JVM直接内存-CSDN博客

7. JVM类加载器与双亲委派模型-CSDN博客

8. JVM类装载的执行过程-CSDN博客

9. JVM垃圾回收-CSDN博客

10. 垃圾回收的算法-CSDN博客

11. JVM中的分代回收-CSDN博客

12. JVM的垃圾回收器-CSDN博客

13. G1垃圾回收器-CSDN博客

14. 垃圾回收的引用区别-CSDN博客

15. JVM调优的参数设置-CSDN博客

16. JVM调优工具-CSDN博客


1. JVM类装载

类装载(Class Loading) 是Java虚拟机(JVM)将类的字节码文件(.class文件)加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被JVM直接使用的Java类型的过程。

这是Java程序运行的基础机制,也是实现Java"一次编写,到处运行"特性的关键环节。

类装载的核心目标是:

  1. 将类的二进制数据读入内存

  2. 将静态存储结构转换为运行时数据结构

  3. 生成对应的Class对象作为访问入口

  4. 确保加载的类安全有效


2. 类装载的生命周期

类从加载到虚拟机中开始,直到卸载为止,它的整个生命周期包括了:加载、验证、准备、解析、初始化、使用和卸载这7个阶段。

其中,验证、准备和解析这三个部分统称为连接(linking)

1. 加载(Loading)

  • 任务:查找并加载类的二进制数据

  • 过程

    • 通过类的全限定名获取类的二进制字节流

    • 将字节流代表的静态存储结构转换为方法区的运行时数据结构

    • 在堆中生成一个代表该类的Class对象,作为方法区数据的访问入口

  • 特点

    • 数组类由JVM直接创建,不通过类加载器

    • 非数组类的加载可以通过内置或自定义的类加载器完成

2. 验证(Verification)

  • 目的:确保Class文件的字节流符合JVM规范,不会危害虚拟机安全

  • 验证内容

    • 文件格式验证(魔数、版本号等)

    • 元数据验证(语义分析)

    • 字节码验证(程序逻辑验证)

    • 符号引用验证(常量池中的引用检查)

3. 准备(Preparation)

  • 任务:为类变量分配内存并设置初始值

  • 特点

    • 只分配类变量(static变量),不包括实例变量

    • 初始值通常是数据类型的零值(如0、0L、null、false等)

    • 对final static常量会直接赋程序指定的值

4. 解析(Resolution)

  • 任务:将常量池中的符号引用替换为直接引用

  • 解析类型

    • 类或接口的解析

    • 字段解析

    • 方法解析

    • 接口方法解析

  • 特点

    • 解析可能在初始化之后才进行(动态绑定)

    • 如果解析失败会抛出NoSuchMethodError等错误

5. 初始化(Initialization)

  • 任务 :执行类构造器<clinit>()方法

  • 过程

    • 按顺序执行静态变量赋值和静态代码块

    • 保证父类的<clinit>()先于子类执行

    • 接口的<clinit>()不需要先执行父接口的

  • 触发条件(以下情况必须立即初始化):

    1. 使用new、getstatic、putstatic或invokestatic指令时

    2. 反射调用类时

    3. 初始化子类发现父类未初始化时

    4. 虚拟机启动时指定的主类

    5. 使用动态语言支持时相关方法句柄对应的类未初始化

<clinit>()方法详解

<clinit>()是Java编译器自动生成的类构造器方法(Class Constructor Method),它负责执行类的初始化工作。这个特殊的方法名称中的"clinit"是"class initialization"的缩写。

  1. 自动生成

    • 由编译器自动收集类中的所有静态变量赋值语句静态代码块(static{}块)合并产生

    • 如果没有静态变量赋值或静态代码块,编译器不会生成<clinit>()方法

  2. 执行顺序

    • 父类的<clinit>()先于子类执行

    • 静态变量和静态代码块按源代码中的出现顺序执行

    • 接口的<clinit>()不需要先执行父接口的(除非使用父接口的变量)

  3. 线程安全

    • JVM会保证一个类的<clinit>()方法在多线程环境下被正确地加锁同步

    • 如果一个线程正在执行<clinit>(),其他线程会阻塞等待

6. 使用(Using)

  • 类完成初始化后进入使用阶段

  • 可以创建实例、调用方法、访问字段等

7. 卸载(Unloading)

  • 条件

    • 类的所有实例都已被回收

    • 加载该类的ClassLoader已被回收

    • 对应的Class对象没有被引用

  • 特点

    • 由JVM的垃圾回收器完成

    • 卸载通常发生在方法区(元空间)垃圾回收时

    • 由启动类加载器加载的类通常不会被卸载


3. 总结

类装载的执行过程?

  • 加载:查找和导入class文件
  • 验证:保证加载类的准确性
  • 准备:为类变量分配内存并设置类变量初始值
  • 解析:把类中的符号引用转换为直接引用
  • 初始化:对类的静态变量,静态代码块执行初始化操作
  • 使用:JVM 开始从入口方法开始执行用户的程序代码
  • 卸载:当用户程序代码执行完毕后,JM便开始销毁创建的Class对象。

相关推荐
jmxwzy3 分钟前
JVM(java虚拟机)
jvm
Maỿbe31 分钟前
JVM中的类加载&&Minor GC与Full GC
jvm
人道领域2 小时前
【零基础学java】(等待唤醒机制,线程池补充)
java·开发语言·jvm
小突突突2 小时前
浅谈JVM
jvm
饺子大魔王的男人3 小时前
远程调试总碰壁?局域网成 “绊脚石”?Remote JVM Debug与cpolar的合作让效率飙升
网络·jvm
天“码”行空13 小时前
java面向对象的三大特性之一多态
java·开发语言·jvm
独自破碎E18 小时前
JVM的内存区域是怎么划分的?
jvm
期待のcode20 小时前
认识Java虚拟机
java·开发语言·jvm
leaves falling1 天前
一篇文章深入理解指针
jvm
linweidong1 天前
C++ 中避免悬挂引用的企业策略有哪些?
java·jvm·c++