JVM
本文链接:https://blog.csdn.net/feather_wch/article/details/132116849
类文件结构
1、class文件的组成
- 无符号数:基本数据类型 u1 u2 u3 u4 描述
- 数字
- 字符串
- 索引引用
- 表:复合数据类型,无符号数 + 表组, _info结尾
2、class文件是大段字节序
方便阅读
3、class文件的组成部分
- 魔数
- 版本号
- 常量池
- 访问标志
- 类索引
- 父类索引
- 接口索引集合
- 字段表集合
- 方法表集合
java
// 魔数 咖啡
// 版本号
// 常量池
// 访问标志
// 类索引,父类索引,接口索引集合
final class Man extends Person implements IEat, ISleep{
public static final String YEAR = "2023"
String name; // 字段表集合
public void talk(){ // 方法表集合
//
}
}
4、魔数是什么?
- 0xCAFEBABY 咖啡宝贝
- 4byte
5、版本号
- 次版本号:儿子在前 // 质子
- 主版本号:爸爸在后 // 纣王
常量池
6、常量池 = 入口 + 常量池
- 入口:u2,= 多少个常量
- 常量池:1个常量 = 1个表,
- 17种表 = U1 tag + 独立的结构
7、常量池中存放的内容
- 字面量(常量值,String)
- 符号引用
- 类和接口的名称
- 方法的名称和描述符,描述符()Ljava/lang/String;
- 字段的名称和描述符,描述符Ljava/lang/Object;
- 方法句柄和方法类型
- 动态调用点和动态常量
8、方法的描述符 ==> JNI方法描述符
方法的参数类型和返回类型
9、JNI中方法描述符(Method Descriptor)
- 唯一地标识一个方法
- 一个方法描述符为:(Ljava/lang/String;I)V 表示该方法有两个参数,分别为String类型和int类型,返回值类型为void。
10、JVM中方法句柄和方法类型是指什么? ===> 反射机制
- 方法句柄(MethodHandle):可以看作是一个轻量级的函数指针,用于表示对方法的调用。
- 方法类型(MethodType)描述了方法的参数类型和返回类型。
- 两者通常一起使用:
java
Person person = new Person();
MethodType methodType = MethodType.methodType(void.class);
MethodHandle methodHandle = MethodHandles.lookup().findVirtual(Person.class, "sayHello", methodType);
methodHandle.invokeExact(person);
11、JVM中的动态调用点
- 指的是在程序运行时根据实际对象类型来确定要调用的方法。这种调用方式称为【动态分派】 ===> JVM 方法调用
- 动态调用点通常发生在针对多态类型的方法调用中。
- 动态调用点的确定是在运行时发生的,使用了虚方法表(virtual method table)来存储对象的方法信息,以便在运行时进行动态分派。
- 在虚方法表中,每个方法对应一个偏移量,通过偏移量可以找到对应的方法实现。 ===> 虚方法表
12、JVM中的动态常量
- 运行时才确定常量的数值
- 有性能开销
java
public class Main {
public static final int MAX_VALUE = calculateMaxValue();
public static int calculateMaxValue() {
// 这里可以是一些复杂的逻辑来计算最大值
return 100;
}
public static void main(String[] args) {
System.out.println("最大值:" + MAX_VALUE);
}
}
访问标志-access_flags
- class是类、接口、注解还是枚举
- 是否是public、abstract等
类索引
1、类索引是什么?
- 用于到常量池中寻找:类的全限定名
父类索引
- U2
- 用于到常量池中寻找:父类的全限定名
接口索引集合
- 入口 + 索引表集合(U2集合)
- 用于到常量池中寻找:接口的全限定名
字段表集合
- 入口 + 字段表
- 描述类和接口中声明的字段
- 字段表中每一项包含的内容
- 访问标志
- 名称索引 -> 常量池中
- 描述符索引 -> 常量池中
- 属性表集合 = 入口 + 属性表
- 举例:final static int a = 123, 在属性表中会有COnstantValue属性 ===> 类加载阶段
方法表集合
- 入口 + 方法表
- 访问标志 + 名称索引 + 描述索引 + 属性表集合
2、特征签名是什么?
- 方法重载的时候,Java中特征签名 = 方法参数在常量池中符号引用的集合
- class中特征签名 = 返回值 + 方法参数在常量池中符号引用的集合
属性表
1、属性表的主要属性 ===> APT ===> ASM
-
Code
-
Exception
- 和异常表不同 ===> ?
- 展示方法需要检查哪些异常
-
ConstantValue ===> 类加载机制,准备阶段
javaint x = 123; // <init()>实例构造方法中赋值 static int x = 123; // <clinit>类构造器中赋值 final static int x = 123; //ConstantValue属性,在【准备阶段】赋值
2、Code属性的结构
- 属性名
- 属性长度
- 操作数栈最大深度
- 局部变量表的存储空间(slot为单位):不等于局部变量表最大值,会复用
- 字节码长度:总长度
- 字节码指令:多个指令
- aload_0、invokespecial、init等指令
- 异常表
- start_pc
- end_pc
- catch_type
- handler_pc