-
一个类从被加载到虚拟机内存中开始,到卸载出内存为止,整个生命周期包括__7个__阶段
(1) 加载
(2) 验证
(3) 准备
(4) 解析
(5) 初始化
(6) 使用
(7) 卸载
其中,连接包括了 2,3,4 三个步骤, 所以也可以写作 加载 --> 连接 --> 初始化 – > 使用 --> 卸载
-
第一步:加载
(1) 加载阶段要完成__3个__任务
1° 通过一个类的全限定名(完整的包结构)获取定义此类的__二进制字节流__
2° 将这个字节流所代表的静态存储结构,转化为__方法区__的运行时数据结构
3° 在__内存__中(没有规定具体放在哪里)生成一个代表这个类的__java.lang.Class对象__,作为__方法区__中这个类的各种数据的访问入口
(2) 任务1°__没有说明从哪里获得__,所以可以从磁盘class文件、zip包(jar,war)、网络、运行时计算生成、其他文件生成(JSP)、数据库中读取等获得
-
第二步:验证
(1) 目标:Class文件可能通过很多种方式获得,JVM要确定获得的Class文件符合当前虚拟机的要求
(2) 包括
1° 文件格式验证
例如,魔数、版本号、格式是否完整等2° 元数据验证
例如,除Object类以外是否有父类、是否是否实现了父抽象类或接口的所有方法、是否继承了final修饰的父类等3° 字节码验证
验证程序语义是否合法
例如,跳转指令不会跳转到方法体以外、操作数是否类型匹配等4° 符号引用验证
确保解析动作正常执行。事实上,这一步验证发生在解析过程之后
例如,符号引用中通过字符串描述的全限定名是否能找到对应的类、符号引用中的变量、方法是否可以被当前类访问 -
第三步:准备
(1) 目标:为类的静态变量(非final)分配内存并__设置初始值__,这些变量使用的内存在__方法区__
(2) 这一步中仅分配静态变量到方法区中,实例变量会在对象实例化时随着对象分配到Java堆中
(3) 此时的初始值是各种数据类型的“零值”(引用类型的零值为null),不是程序员定义的初始值
(4) 如果是final修饰的类变量,准备阶段虚拟机就会赋值为程序员定义的值(因为放在了常量池中)
-
第四步:解析
(1) 目标:虚拟机将常量池内的符号引用替换为直接引用
(2)
符号引用:在Class文件中,以一组符合描述所引用的目标,解析时针对__7类__符号引用:类或接口、字段、类方法、接口方法、方法类型、方法句柄、调用点限定符
直接引用:直接指向目标的指针、相对偏移量、句柄,和内存中引用目标相关
-
第五步:初始化
(1) 目标:根据程序员指定的主观计划,初始类变量和其他资源。即,执行类构造器()方法的过程。
(2) 虚拟机会保证在子类的()方法执行之前,父类的()方法已经执行完毕。所以,父类的静态语句、变量先于子类执行、赋值。
(3) ()方法是编译器自动收集类中所有的静态变量的赋值动作和静态语句块中的语句合并产生是。 编译器收集的__顺序__是由语句在源文件中出现的顺序决定。
(4) 静态语句块可以访问定义在静态语句块之前的静态变量,不能访问定义在静态语句块之后的静态变量,但是可以赋值
(5) 接口中不能使用静态语句块,但是可以有变量初始化的赋值操作。与类不同的是,执行接口的()方法不需要先执行父接口的()方法,接口的实现类在初始化时也不会执行接口的()方法
(6) 虚拟机会保证一个类的()方法在多线程环境下可以被正确的加锁、同步,因此多线程同时初始化一个类的时候,只有一个线程会执行这个类的()方法。同一个类加载器下,一个类型只会初始化一次
chapter07_虚拟机类加载机制_3_类加载的过程
最新推荐文章于 2025-08-05 23:03:41 发布
本文详细阐述了Java类从加载到虚拟机内存开始,直至卸载的整个生命周期,包括加载、验证、准备、解析、初始化、使用和卸载七个阶段。深入解析每个阶段的任务和目标,如类的二进制字节流获取、方法区数据结构转化、静态变量内存分配与初始化、符号引用的解析等关键概念。
664

被折叠的 条评论
为什么被折叠?



