8.1.2 常量池的结构

下面介绍定义常量池中的常量的cp_info结构。每个常量定义的起始字节的值标明了常量的类型。我们将该字节称为标签。在这个字节之后是包含常量内容的若干个字节。先介绍Java基本类型常量的定义方式。字节代码中只包含基本类型int、long、float和double的对应表示,其他基本类型都可以用int来表示。在这4种类型中,int和float类型的常量的内容是在标签后紧跟包含数据的4个字节;long和double类型的常量则在标签后紧跟8个字节。值得注意的是,long和double类型的常量会占用常量池中的两个位置。在进行计算时需要考虑这一点。

常量CONSTANT_Utf8_info表示的是一个使用修改后的UTF-8格式表示的字符串序列。在标签之后的两个字节表示序列的长度,紧接着是序列的内容。这种类型的常量在字节代码中的出现次数比较多。表示String类型的常量CONSTANT_String_info直接引用CONSTANT_Utf8_info常量,只包含一个对应的常量池中的序号。常量CONSTANT_Class_info表示类或接口,在标签后接着的是类或接口的全名对应的CONSTANT_Utf8_info常量的序号。对于类或接口中包含的域和方法,由两类常量来共同表示:第一类常量CONSTANT_NameAndType_info表示域和方法的名称和类型,分别由两个CONSTANT_Utf8_info常量来表示;第二类常量表示域和方法与类或接口的对应关系。常量CONSTANT_Fieldref_info、CONSTANT_Methodref_info和CONSTANT_InterfaceMethodref_info分别表示域、类中的方法和接口中的方法。这三种常量的结构是相似的,在标签之后分别是表示所在类或接口的CONSTANT_Class_info常量和表示名称与类型的CONSTANT_NameAndType_info常量的序号。从上面对常量池中常量的说明可以看出,常量之间存在复杂的引用关系。通过这种引用关系,可以最大限度地复用已有的内容,避免重复。

表示域的field_info结构的格式如代码清单8-2所示。

代码清单8-2 表示域的field_info结构的格式


u2 访问控制标记和属性修饰符

u2 名称的常量的序号

u2 类型描述符的常量的序号

u2 属性的个数


attribute_info 包含属性信息的数组

域的访问控制标记和属性修饰符的表示方式与类或接口中的表示方式很相似,只是所能使用的访问控制标记和修饰符的种类不同。域的名称和类型描述符的表示方式与常量CONSTANT_NameAndType_info是相同的。域的属性是在个数后接着一个包含attribute_info结构的数组。表示方法的method_info结构的格式与代码清单8-2中的field_info的格式是相同的。