满嘴都是糖果

Class类文件结构

Class文件格式采用两种数据类型:无符号数与表

无符号数:以u1、 u2、 u4、 u8来分别代表1个字节、 2个字节、 4个字节和8个字节的无符号数 ,可以用来描述数字索引引用数量值或者按照UTF-8编码构成字符串值

表:由多个无符号数或者其他表构成的复合数据结构,习惯性以”_info”为后缀

上图是Class文件的数据项表格,其有着严格的规定。

魔数

每个Class文件的头四个字节被称为魔数,用于校验这个文件是否是一个能被虚拟机接受的Class文件,而并不以文件的后缀名校验。魔数值为0xCAFEBABE

Class文件版本

魔数后面的4个字节存储Class文件的版本号,前两个字节为次版本号,后两个字节为主版本号,版本号从45开始,JDK1.1后每个版本都在主版本号后+1,虚拟机只能向下兼容。

常量池

常量池是Class文件的资源池,由于数量不固定,入口需使用u2类型声明容量计数值,计数从1开始,0 用于“不引用任何一个常量池项目”的特殊场合。

常量池存放两大类常量:字面量和符号引用。

字面量:顾名思义,比如字符串,被final修饰的常量值。

符号引用:包含被模块导出或者开放的包、类和接口的全限定名、字段的名称和描述符、方法的名称和描述符、方法句柄和方法类型、动态调用点和动态常量

可以使用 javap -verbose 命令获取字节码内容

访问标志

常量池后面两个字节代表访问标识,用于标识一些类或者接口层次的访问信息

类索引 父类索引 接口索引

类索引:u2类型数据,用于确定类的全限定名

父类索引:u2类型数据,用于确定父类的券限定名,除了Object外,所有的父类索引都不为0

接口索引:多个u2类型数据的集合,用于描述这个类实现了哪些接口

字段表集合

用于描述接口或者类中声明的变量,包含类级变量和实例级(static)变量,但是不会列出继承来的字段。

access_flags描述字段的访问标识,分为是否为public、private、protected、static、final、volatile、transient、enum以及是否由编译器自动产生。

name_index表示字段的简单名称

descriptor_index表示方法的描述符,如 java.lang.String[][]类型的二维数组的描述符为[[Ljava/lang/String

attribute_info为属性表,存储一些额外信息

方法表集合

用于描述类中的方法,形式类似于字段表,没有重写方法的话,也是不会列出父类的方法信息

方法中的代码,经过javac编译器编译成字节码指令后,存放于方法表”Code“属性里面。

描述符 例如方法java.lang.String.toString()将被存储为()Ljava/lang/String

属性表集合

每个属性的名称都需从常量池中引用一个CONSTANT_Utf8_info类型的常量来表示 ,虚拟机预定义属性已经增加到29项