JVM---ClassFile的文件结构解析


Java虚拟机规范规定的,class文件格式采用的类似C语言的结构体的伪结构来存储的。
这种结构只有两种数据类型 :无符号数 和 表

1.无符号数

属于基本数据类型 主要用于描述数字 索引符号 数量值 或者按照UTF-8编码构成的字符串值。
数据类型 U1 U2 U4 U8 也只是逻辑上的区分。
u1 —表示一个字节
u2 —表示两个字节
u4,u8 — 依次类推

2.表

由多个无符号数或者其他表作为数据项构成的复合数据类型。所有的表都习惯以
_info结尾 表主要用于描述有层次关系的复合结构数据。比如 方法、字段 需要
注意的是class文件没有分隔符,所以每个二进制数据类型都是严格定义的 具体的
顺序如下:

在这里插入图片描述

3 ClassFile的文件结构解析

3.1 magic(魔术)

每个Class文件的头4个字节称为魔数(Magic Number)
唯一作用是用于确定这个文件是否为一个能被虚拟机接受的Class文件。
Class文件魔数的值为0xCAFEBABE。如果一个文件不是以0xCAFEBABE开头,那它就肯定不是Java class文件。

3.2 class文件版本号

紧挨着魔术的4个字节表示class的文件的版本号 版本号:
1.次版本号 --minor_version 前2个字节用于表示次版本号 例如:00 00
2.主版本号 --major_version 后2个字节用于表示主版本号 例如: 00 34
Java的版本号是从45开始的。如果class的版本号超过虚拟机的版本 会被拒绝执行。
JDK1.2 ----0X002E 46
JDK1.3 ----0X002F 47
JDK1.4 ----0X0030 48
JDK1.5 ----0X0031 49
JDK1.6 ----0X0032 50
JDK1.7 ----0X0033 51
JDK1.8 ----0X0034 52

3.3 constant_pool_count

版本号后面是常量池的个数,占两个字节。
constant_pool_count 从1开始计数的。 class文件结构中只有常量池的容量计数是从1开始的。第0项腾出来满足后面某些指向常量池的索引值的数据,在特定的情况下需要表达“不引用任何一个常量池项目” 把索引值的第0项留给JVM自己用。

3.4 constant_pool

长度为 constant_pool_count-1

常量池详细解析常量类型总共有18个编号的常量类型。

constant_pool的具体内容:索引,标志tag,类型
1.编号1: CONSTANT_UTF8_INFO
Tag1 ------占用一个空间字节
Length: utf-8字符串占用的字节数
Bytes 长度为length字符串
用于表示utf-8的编码的字符串

3.编号3 CONSTANT_integer_info
Tag3
Bytes 4个字节 Big_Endian(高位在前) 存储int类型的值

4.编号4 CONSTANT_float_info
Tag4
Bytes 4个字节 Big_Endian(高位在前) 存储float类型的值

5.编号5 CONSTANT_long_info
Tag5
Bytes 8个字节 Big_Endian(高位在前) 存储long类型的值

6.编号6 CONSTANT_double_info
Tag6
Bytes 8个字节 Big_Endian(高位在前) 存储double类型的值

7.编号7 CONSTANT_Class_info
Tag7
Index 2个字节 指向类的全限定名的项的索引
类和接口符号引用

8.编号8 CONSTANT_String_info
Tag8
Index 2个字节 指向字符串的字面量的索引

9.编号9 CONSTANT_Fieldref_info
Tag9
Index 2个字节 指向声明字段的类或接口的描述符 CONSTANT_Class_info的索引项
Index 2个字节 指向字段描述符CONSTANT_NameAndType的索引项
字段的符号引用

10.编号10 CONSTANT_Methodref_info
Tag10
Index 2个字节 指向声明字段的类或接口的描述符 CONSTANT_Class_info的索引项
Index 2个字节 指向字段描述符CONSTANT_NameAndType的索引项
类中方法的符号引用

11.编号11 CONSTANT_InterfaceMethodref_info
Tag11
Index 2个字节 指向声明字段的类或接口的描述符 CONSTANT_Class_info的索引项
Index 2个字节 指向字段描述符CONSTANT_NameAndType的索引项
接口中方法的符号引用

12.编号12 CONSTANT_NameAndType
Tag12
Index 2个字节 指向该字段或方法名称常量项的索引
Index 2个字节 指向该字段或方法描述符常量项的索引
字段或方法的符号引用

15.编号15 CONSTANT_MethodHandler_info
Tag15
Reference_kind 1个字节 1-9之间的一个值 决定了方法句柄的类型。方法句柄类型的值表示方法句柄的字节码行为
Reference_index 2个字节 对常量池的有效索引。
表示方法句柄

16.编号16 CONSTANT_MethodType_info
Tag16
Descriptor_index 2个字节 指向UTF8_info 结构表示的方法描述符

18.编号18 CONSTANT_InvokeDynamic_info
Tag18
Bootstrap_method_attr_index: 2个字节 当前class文件中引导方法表的bootstrap_methods[] 数组的有效索引
Name_and_type_index: 2个字节 指向NameAndType_info 表示方法名和方法描述符。
表示动态方法的调用点。

3.5 access_flag

用于表示对该类或接口的访问权限以及该类或接口的属性
在这里插入图片描述

3.6 this_class

该this_class 项目的值 必须是constant_pool表中的有效索引,该constant_pool索引处的条目必须是表示此文件定义的类或接口 CONSTANT_Class_info 结构class

3.7 super_class

必须是constant_pool表中的有效索引, 如果super_class的值不为0 则constant_pool中的条目必须为CONSTANT_Class_info 结构 这个结构表示此类的文件定义的类的直接超类。直接超类不能在其classfile结构的access_flag项中设置 ACC_FINAL 标志。
其实要描述的意思就是说 如果superclass指代的超类,那么它就不能被final修饰。

3.8 intefaces_count和 intefaces

intefaces_count表示的接口的数量,两个字节
intefaces 表示接口名,两个字节

3.9 fields_count 和 fields

fields_count表示域的数量,两个字节
fields 表示域的表
1.名称access_flag 类型u2 数量1个
2.名称 name_index 类型u2 数量1个 -
3. 名称 descriptior_index 类型u2 数量1个
4. 名称 descriptior_index 类型u2 数量1个
(1) 参数列表(参数类型) 后-返回值
(2) void m() 等同于 ()V
(3) String toString() ->()Ljava/lang/String;
(4) Long pos(int[] arr1,int arr2,long length) ->([IIJ)J
[ 一维数组 [[ 表示二维数组
在这里插入图片描述
(5)attributes_count 附加属性的数量
(6)attributes 附加属性

3.10 method_count 和 method

  method_count  表示方法的数量
  method表示方法表

1.名称access_flag 类型u2 数量1个
2.名称 name_index 类型u2 数量1个 -
3. 名称 descriptior_index 类型u2 数量1个
4. 名称 descriptior_index 类型u2 数量1个
(1) 参数列表(参数类型) 后-返回值
(2) void m() 等同于 ()V
(3) String toString() ->()Ljava/lang/String;
(4) Long pos(int[] arr1,int arr2,long length) ->([IIJ)J
[ 一维数组 [[ 表示二维数组
(5)attributes_count 附加属性的数量
(6)attributes 附加属性

3.11 attribute_count 和 attribute

attribute_count 表示附加的属性数量 两个字节
attribute 表示附加属性表
附加属性 方法中的附加属性就是code,那么code在这里是比较重要的概念,code是具体代码的实现,当我们写入方法的时候,它能够把方法中代码转化为一条条指令。
在这里插入图片描述
Attributes附加属性
附加属性中 有的代码中存在内容,有的不存在内容
1.既有预定义的属性,也可以自定义 java虚拟机会自动忽略它不认识属性
2. Code 表示的是方法表 方法表能够编译成字节码指令,还存放了操作数栈和局部变量的信息
在这里插入图片描述 (1)u2 attribute_name_index 指向常量池中的CONSTANT_UTF8_info 存放的当前属性的名字就是code。
(2)u4 attribute_length 表示的code属性的长度 (不包括前6个字节)。
(3)u2 max_stack 指定当前方法被执行引擎执行的时候,在栈帧中需要分配的操作数栈的大小
(4)u2 max_locals 指定当前方法被执行引擎执行的时候,在栈帧中需要分配的局部变量表的大小
(5)u4 code_length 指定方法字节码的长度, class文件中每条字节码都占用一个字节
(6)u1 code 存放字节码指令本身,它的长度是code_length个字节。
(7)u2 exception_table_length指定异常表的大小
(8)Exception_table异常表 作用对try-catch-finally的描述,可以把它看成是一个数组。每一个数组项都是一个exception_info结构, 一般来说每个catch块对应一个exception_info,编译器也可能会对当前的方法生成一些exception_info.
在这里插入图片描述
u2 start_pc 是从字节码code属性中的一部分 起始处到当前异常处理器的起始处的偏移量量

u2 end_pc 从字节码起始处到当前异常处理器 末尾的偏移量

u2 handler_pc 是指当前异常处理器用于处理异常(即catch块)的第一条指令相对于字节码开始处的偏移量。

u2 catch_type 是常量池的索引 指向的是常量池CONSTANT-Class_info 数据项,描述了catch块中的异常类型的信息。这个类必须是java.lang.Throwable的或者是它的子类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值