Class文件

Catalogue   

概述

Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在 Class文件之中,中间没有添加任何分隔符。根据Java虚拟机规范的规定,
Class文件结构采用一种 类似于C语言结构体的伪结构来存储数据,这种伪结构只有两种数据类型:无符号数和表。

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

魔数与Class文件的版本

每个Class文件的头四个字节称为魔数(Magic Number),值为0xCAFEBABE。紧跟着魔数的四个字节存储的是Class文件的版本号:第5和第6个字节是次版本号(Minor Version),
第7和第8个字节是主版本号(Major Version)。

常量池(constant_pool)

由于常量池中的常量数量不固定,所以在常量池的入口需要放置一项u2类型的数据,代表容量池容量计数值(constant_pool_count),这个容量计数从1而不是0开始。

常量池中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic Reference)。字面量 比较接近Java语言层面的常量概念,如文本字符串、声明为final的常量值等。
而符号引用则属于编译原理方面的概念,包括下面三类常量:

  • 类和接口的全限定名
  • 字段的名称和描述符
  • 方法的名称和描述符

JDK1.7中,总共有14种类型的常量,每种常量都是表类型的数据项。这14种表都有一个共同的特 点,就是表开始的第一位是一个u1类型的标志位,代表当前常量属于哪种常量类型。
这14种常量类型代表的具体含义见下表:

访问标志(access_flags)

常量池结束之后,紧接着的两个字节代表访问标志,这个标志用于识别一些类或者接口层次的访问信息,包括:这个Class是接口还是类;是否被定义为public类型;
是否定义为abstract类型;如 果是类的话,是否被声明为final等。

类索引(this_class)、父类索引(super_class)与接口索引集合(interfaces)

类索引、父类索引和接口索引集合都按顺序排列代访问标志之后,类索引用于确定这个类的全限 定名,父类索引用于确定这个类的父类的全限定名。
由于Java语言不允许多继承,因此父类索引只有一个,除了java.lang.Object之外,所有的Java类都有父类,因此除了Object外,所有Java类的父类索引都不为0。

类索引和父类索引均是u2类型的数据,它们各自指向一个类型为CONSTANT_Class_info类型的常 量,通过CONSTANT_Class_info类型的常量中的索引值可以找到
定义在CONSTATN_Utf8_info类型 的常量中的全限定名字符串。该查找过程可用下图表示

接口索引集合用来描述这个类实现了哪些接口,它是一组u2类型的数据的集合,集合中的第一项 是接口计数器,表示索引表的容量。如果一个类没有实现任何接口,
则该计数器值为0。

字段表集合(fields)

方法表集合(methods)

属性表集合(attributes)