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对象。

相关推荐
小羊没烦恼!7 小时前
JVM调优实战指南:让Java程序性能飞升的奥秘
jvm
小屁孩大帅-杨一凡7 小时前
如何解决ThreadLocal内存泄漏问题?
java·开发语言·jvm·算法
兮动人12 小时前
Java应用全链路故障排查实战指南:从系统资源到JVM深度诊断
java·开发语言·jvm
morningcat201815 小时前
java17 gc笔记
java·jvm·笔记
共享家952715 小时前
linux_线程概念
linux·开发语言·jvm
想躺平的咸鱼干1 天前
JVM的垃圾回收算法和多种GC算法
java·jvm·算法·垃圾回收算法·jvm体系结构
sqyaa.1 天前
Guava LoadingCache
jvm·缓存·guava
大佐不会说日语~2 天前
JVM类加载机制解析
jvm
我尽力学2 天前
JVM相关
jvm