Class文件格式采用两种数据类型:无符号数与表
无符号数:以u1、 u2、 u4、 u8来分别代表1个字节、 2个字节、 4个字节和8个字节的无符号数 ,可以用来描述数字、 索引引用、 数量值或者按照UTF-8编码构成字符串值。
表:由多个无符号数或者其他表构成的复合数据结构,习惯性以”_info”为后缀
上图是Class文件的数据项表格,其有着严格的规定。
每个Class文件的头四个字节被称为魔数,用于校验这个文件是否是一个能被虚拟机接受的Class文件,而并不以文件的后缀名校验。魔数值为0xCAFEBABE
魔数后面的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项