类加载子系统,
加载 链接(验证 准备 解析) 初始化
验证 .class 文件格式是否正确
准备: 准备static变量信息 为static变量初始化 并赋0值
解析:将符号引用解析为直接引用,比如对象之间通过引用,变成直接引用对象的引用地址,类似于从使用相对路径到使用绝对路径。
类加载子系统
类加载子系统:通过类加载机制加载类的class文件,如果该类是第一次加载,会执行加载、验证、解析。只负责class文件的加载,至于是否可运行,则由执行引擎决定。
JVM中,类加载过程是在类加载子系统完成的。
类加载过程:加载 --> 链接(验证 --> 准备 --> 解析) --> 初始化
类加载过程:加载、链接(验证、准备、解析)、初始化。这个过程是在类加载子系统完成的。
加载:生成类的Class对象。
通过一个类的全限定名获取定义此类的二进制字节流(即编译时生成的类的class字节码文件)
将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。包括创建运行时常量池,将类常量池的部分符号引用放入运行时常量池。
在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类各种数据的访问入口。注意类的class对象是运行时生成的,类的class字节码文件是编译时生成的。
链接:将类的二进制数据合并到JRE中。该过程分为以下3个阶段:
验证:确保代码符合JAVA虚拟机规范和安全约束。包括文件格式验证、元数据验证、字节码验证、符号引用验证。
文件格式验证:验证字节码文件是否符合规范。
魔数:是否魔数0xCAFEBABE开头
版本号:版本号是否在JVM兼容范围
常量类型:类常量池里常量类型是否合法
索引值:索引值是否指向不存在或不符合类型的常量。
元数据验证:元数据是字节码里类的全名、方法信息、字段信息、继承关系等。
标识符:验证类名接口名标识符有没有符合规范
接口实现方法:有没有实现接口的所有方法
抽象类实现方法:有没有实现抽象类的所有抽象方法
final类:是不是继承了final类。
指令验证:主要校验类的方法体,通过数据流和控制流分析,保证方法在运行时不会危害虚拟机安全。
类型转换:保证方法体中的类型转换是否有效。例如把某个类强转成没继承关系的类
跳转指令:保证跳转指令不会跳转到方法体以外的字节码指令上;
保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作。
符号引用验证:确保后面解析阶段能正常执行。
类全限定名地址:验证类全限定名是否能找到对应的类字节码文件
引用地址:引用指向地址是否存在实例
引用权限:是否有权引用
准备:为类变量(即static变量)分配内存并赋零值。
解析:将方法区-运行时常量池内的符号引用(类的名字、成员名、标识符)转为直接引用(实际内存地址,不包含任何抽象信息,因此可以直接使用)。
初始化:类变量赋初值、执行静态语句块。
运行时数据区
2.2.0 基本介绍
运行时数据区:在程序运行时,存储程序的内容(例如字节码、对象、参数、返回值等)。
运行时数据区包括本地方法栈、虚拟机栈、方法区、堆、程序计数器。
在运行时数据区中,只有方法区和堆是各线程共享的进程内存区域,其他运行区都是每个线程可以独立拥有的。
栈帧:栈帧是栈的元素,由三部分组成,即局部变量表(存方法参数和局部变量)、操作数栈(存方法执行过程中的中间结果,或者其他暂存数据)和帧数据区(存方法返回地址、线程引用等附加信息)。
常量池:就是一张表,JVM根据这张常量表找到要执行的类信息和方法信息
类常量池:是.class字节码文件中的资源仓库,主要存放字面量(表示字符串值和数值,例如字符串值"abc"、final常量、静态变量)和符号引用(类和接口的全限定名、字段名、方法名)。
运行时常量池:类加载的“加载”阶段会创建运行时常量池,统一存放各个类常量池去重后的符号引用。在类加载的“解析”阶段JVM会把运行时常量池的这些符号引用转为直接引用。类常量池。类常量池在字节码文件中的,运行时常量池在内存中。
字符串常量池:专门针对String类型设计的常量池。是当前应用程序里所有线程共享的,每个jvm只有一个字符串常量池。存储字符串对象的引用。在创建String对象时,JVM会先在字符串常量池寻找是否已存在相同字符串的引用,如果有的话就直接返回引用,没的话就在堆中创建一个对象,然后常量池保存这个引用并返回引用。
类常量池:是.class字节码文件中的资源仓库,主要存放字面量(表示字符串值和数值,例如字符串值"abc"、final常量、静态变量)和符号引用(类和接口的全限定名、字段名、方法名)。
类常量池在方法区里面,在类加载过程
类加载过程:加载、链接(验证、准备、解析)、初始化。这个过程是在类加载子系统完成的。
加载:生成类的Class对象 。
通过一个类的全限定名获取定义此类的二进制字节流(即编译时生成的类的class字节码文件)
将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。包括创建运行时常量池,将类常量池的部分符号引用放入运行时常量池。
在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类各种数据的访问入口。注意类的class对象是运行时生成的,类的class字节码文件是编译时生成的。
参考链接:https://blog.csdn.net/qq_40991313/article/details/134742377