1.简介
- 是什么:Class文件是一组以8个字节为基础单位的二进制流,中间没有添加任何分隔符整个Class文件本质上也可以视作是一张表。
-
任何一个 Class 文件都对应着 唯一 的一个类或接口的定义信息。 但是反过来说,类或 接口并不一定都得定义在文件里(譬如类或接口也可以动态生成,直接送入类加载器中)。
-
数据结构:Class 文件格式采用一种类似于 C 语言结构体的 伪结构 来存储数据,这种伪结构中 只有两种数据类型 : “ 无符号数 ” 和 “ 表 ” 。
-
无符号数 属于 基本的数据类型 , 以 u1 、 u2 、 u4 、 u8 来分别代表 1 个字节(8bit)、 2 个字节、 4 个字节和 8 个 字节的无符号数, 可以用来描述数字、索引引用、数量值或者按照UTF-8 编码构成字符串 值。
- 表 是由多个无符号数或者其他表作为数据项构成的复合数据类型 ,用于描述有层次关系的复合结构的数据。
-
- 类文件作用:它上承各种 JVM 系编程语言,下接虚拟机。Java 虚拟机完全依赖 class 格式的二进制作为输入,经过类加载器,加载进入元空间的方法区。
- 如何查看:JClassLib ----IDEA插件
2.结构组成
(1)总体结构
类型 | 名称 | 说明 | 长度 | 数量 |
---|---|---|---|---|
U4 | magic | 魔数 识别Class文件 | 4 字节 | 1 |
U2 | minor_version | 副版本号(小版本) | 2字节 | 1 |
U2 | major_version | 主版本号(大版本) | 2字节 | 1 |
U2 | constant_pool_count | 常量池计数器 | 2字节 | 1 |
cp_info | constant_pool | 常量池表 | n字节 | constant_pool_count |
U2 | access_flags | 访问标识 | 2字节 | 1 |
U2 | this_class | 类索引 | 2字节 | 1 |
U2 | super_class | 父类索引 | 2字节 | 1 |
U2 | interfaces_count | 接口计数器 | 2字节 | 1 |
U2 | interfaces | 接口索引集合 | 2字节 | interfaces_count |
U2 | fields_count | 字段计数器 | 2字节 | 1 |
field_info | fileds | 字段表 | n字节 | fields_count |
U2 | methods_count | 方法计数器 | 2字节 | 1 |
method_info | methods | 方法表 | n字节 | methods_count |
U2 | attributes_count | 属性计数器 | 2字节 | 1 |
attribute_info | attributes | 属性表 | n字节 | attributes_count |
(2)魔数与Class文件的版本
- 每个Class文件的头4个字节被称为魔数(Magic Number)它的唯一作用是确定这个文件是否为 一个能被虚拟机接受的Class文件。
-
紧接着魔数的 4 个字节存储的是 Class 文件的 版本号
-
第5和第6个字节是次版本号(MinorVersion)
-
第7和第8个字节是主版本号(Major Version)
-
JDK 1.1之后 的每个JDK大版本发布主版本号向上加1(JDK 1.0~1.1使用了45.0~45.3的版本号)
-
高版本的JDK能 向下兼容以前版本的Class文件,但不能运行以后版本的Class文件
-
(3)常量池🔥🔥
-
常量池可以比喻为 Class文件里的资源仓库,包括:常量池计数器、常量池表。
-
占用Class文件空间最大的数据项目之一。
-
常量池中常量的数量是不固定的 。 常量池计数器下标是 从1而不是0开始 常量池容量(偏移地址: 0x00000008 )为十六进制数 0x0016 ,即十进制的 22 ,这就 代表常量池中有 21 项常量,索引值范围为 1 ~ 21。
-
常量池中主要存放两大类常量:
-
字面量(Literal):文本字符串、声明为final的常量值等
-
符号引用(Symbolic References):
-
类和接口的全限定名 假如类Test所在的包名为:com.example,则该类的全限定名为:com/example/Test
-
字段的名称和描述符 这里的名称指的的简单名称,比如定义一个字段
int age = 20
,那么名称即为age
。 描述符的作用是用来描述字段的数据类型、方法的参数列表(包括数量、类型以及顺序)和返回值的,见下表: -
方法的名称和描述符 这里的名称指的的简单名称,比如方法
toString()
的名称即为toString
。描述符作用同上
-
-
常量池中的数据结构类型
-
-
(3)访问标志 access_flags
- 用于识别类或者接口层次的访问信息, 包括这个Class文件是类还是接口,是否被定义为public类型,是否定义为abstract类型;如果是类是否被声明为final等;
- 访问标志是一个u2类型的数据项,常量池结束后,紧接着的两个字节就代表着访问标志的值;
- 官方定义中访问标志一共有十六种标志位可以使用, 当前只定义了其中8个, 没有使用到的标志位要求一律为0.将所有使用到的标志位做或位运算得到的最后的值即为访问标志的值;