Class 文件结构

反汇编:javap -c xxxx.class 使用 -v 可以多打印一些信息

Java 技术能够一直保持非常好的向后兼容性,这点 Class 文件结构的稳定性功不可没。class 文件结构的内容,绝大部分在 JDK1.2 时代就已经定义好了。每次基本上只是在原有结构基础上新增内容、扩充功能,并未对定义的内容做修改。
任何一个Class 文件都对应着唯一一个类或接口的定义信息,但反过来说,Class 文件实际上它并不一定以磁盘文件的形式存在(比如可以动态生成、或者直接送入类加载器中)。Class 文件是一组以 8 位字节为基础单位的二进制流

Class 文件格式采用一种类似于C 语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:无符号数和表

  • 无符号数属于基本的数据类型,以 u1、u2、u4、u8 来分别代表 1 个字节(一个字节是由两位 16 进制数组成)、2 个字节、4 个字节和 8 个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照 UTF-8 编码构成字符串值。
  • 表是由多个无符号数或者其他表作为数据项构成的复合数据类型,所有表都习惯性地以“_info”结尾。表用于描述有层次关系的复合结构的数据,整个 Class 文件本质上就是一张表。

文件结构(按顺序):

No.结构说明
1magic(u4)cafe babe,魔数
2minor_version(u2)次版本号
3major_version(u2)主版本号,从 45 开始;JDK1.8 是52
4constant_pool_count(u2)容量计数是从 1 开始而不是 0
5constant_pool常量池内容
6access_flags(u2)表示某个类或者接口的访问权限和属性
7this_class(u2)类索引,必须是一个 CONSTANT_Class_info 类型的结构体,表示这个 class 文件所定义的类和接口。用于确定这个类的全限定名
8super_class(u2)父类索引,除 java.lang.Object 外,都不为 0
9interfaces_count(u2)接口计数器,表示当前类或者接口直接继承接口的数量
10interfaces(u2)接口表,是一个表结构,是对常量池中 CONSTANT_Class_info 类型的一个有效索引值
11fields_count(u2)字段计数器,当前 class 文件所有字段的数量
12fields字段表,是一个表结构,每个成员必须是 filed_info 数据结构,用于表示当前类或者接口的某个字段的完整描述,但它不包含从父类或者父接口继承的字段。但有可能列出原本 Java 代码之中不存在的字段,譬如在内部类中为了保持对外部类的访问性,会自动添加指向外部类实例的字段
描述接口或者类中声明的变量。字段(field)包括类级变量以及实例级变量。而字段叫什么名字、字段被定义为什么数据类型,这些都是无法固定的,只能引用常量池中的常量来描述。
13methods_count(u2)方法计数器,表示当前类方法表的成员个数
14methods方法表,是一个表结构,每个成员必须是 method_info 数据结构,用于表示当前类或者接口的某个方法的完整描述
描述了方法的定义,但是方法里的 Java 代码,经过编译器编译成字节码指令后,存放在属性表集合中的方法属性表集合中一个名为“Code”的属性里面。
与字段表集合相类似的,如果父类方法在子类中没有被重写(Override),方法表集合中就不会出现来自父类的方法信息。
但同样的,有可能会出现由编译器自动添加的方法,最典型的便是类构造器<clinit>方法和实例构造器<init>
15attributes_count(u2)属性计数器,表示当前 class 文件 attributes 属性表的成员个数
16attributes属性表,是一个表结构,每个成员必须是 attribute_info数据结构,这里的属性是对 class 文件本身,方法或者字段的补充描述,比如 SourceFile 属性用于表示 class 文件的源代码文件名
存储 Class 文件、字段表、方法表都有自己的属性表集合,以用于描述某些场景专有的信息。如方法的代码就存储在 Code 属性表中。

常量池(constant_pool)

常量池中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)
字面量比较接近于 Java 语言层面的常量概念,如文本字符串、声明为 final 的常量值等。
而符号引用则属于编译原理方面的概念,包括了下面三类常量:
类和接口的全限定名(Fully Qualified Name)、字段的名称和描述符(Descriptor)、方法的名称和描述符

类型tag(u1)内容
CONSTANT_Utf8_info1length(u2) UTF-8 字符串占用的字节数
bytes(u1) 长度为 length 的字符串
CONSTANT_Integer_info3bytes(u4) 按照高位在前存储的 int 值
CONSTANT_Float_info4bytes(u4) 按照高位在前存储的 float 值
CONSTANT_Long_info5bytes(u8) 按照高位在前存储的 long 值
CONSTANT_Double_info6bytes(u8) 按照高位在前存储的 double 值
CONSTANT_Class_info7index(u2) 指向全限定名常量项的索引
CONSTANT_String_info8index(u2) 指向字符串字面量的索引
CONSTANT_Fieldref_info9index(u2) 指向声明字段的类或者接口描述符CONSTANT_Class_info 的索引项
index(u2) 指向字段描述符CONSTANT_NameAndType_info 的索引项
CONSTANT_Methodref_info10index(u2) 指向声明方法的类描述符CONSTANT_Class_info 的索引项
index(u2) 指向名称及类型描述符CONSTANT_NameAndType_info 的索引项
CONSTANT_InterfaceMethodref_info11index(u2) 指向声明方法的接口描述符CONSTANT_Class_info 的索引项
index(u2) 指向名称及类型描述符CONSTANT_NameAndType_info 的索引项
CONSTANT_NameAndType_info12index(u2) 指向该字段或方法名称常量的索引
index(u2) 指向该字段或方法描述符常量项的索引
CONSTANT_MethodHandle_info15reference_kind(u1) 值在1~9之间,他决定了方法句柄的类型。方法句柄类型的值表示方法句柄的字节码行为
reference_index(u2) 值必须是对常量池的有效索引
CONSTANT_MethodType_info16descriptor_index(u2) 值必须是堆常量池的有效索引,常量池在该索引下的项必须是 CONSTANT_Utf8_info 接口,表示方法的描述符
CONSTANT_InvokeDynamic_info18bootstrap_method_attr_index(u2) 值必须是对当前 Class 文件中引导方法表的 bootstrap_methods[] 数组的有效索引
name_and_type_index(u2) 值必须是对当前常量池的有效索引,常量池在该索引出的项必须是CONSTANT_MethodType_info 结构,表示方法名和方法描述符
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值