类型 | 名称 | 数量 |
u2 | major_version主版本号 | 1 |
u2 | constant_pool_count常量池 | 1 |
cp_info | constant_pool | constant_pool_count-1 |
常量池:在版本后面,使用2个字节空间存储常量个数,紧接 cp_info 表结构逐个显示常量。也可喻为 class 文件资源仓库,还是 class 文件中第一个出现的表类型数据项目。
例如:常量池容量(偏移地址:0x00000008)为十六进制 0x0013,即10进制19,代表常量池中有18项常量。class 文件结构只有常量池的容量计数是从1开始,对于其他集合类型,包括接口索引集合,字段表集合,方法表集合的容量计数都是从0开始。
常量池主要存放两大类常量:字面量(Literal) 和 符号引用(Symbolic References)
1. 字面量比较接近于java 语言层面的常量概念,如文本字符串,被声明为 final 常量值。
2. 而符号引用则属于编译原理方面概念,主要包括:
- 被模块导出或开发的包(Package)
- 类和接口的全限定名(Full Qualified Name)
- 字段的名称和描述符(Descriptor)
- 方法的名称和描述符
- 方法句柄和方法类型(Method Handle Method Type ,Invoke Dynamic)
- 动态调用点和动态常量(Dynamically-Computed Call Stie, Dynamically-Computed Constant)
常量池中每项常量都是一个表,最初常量表中有11种表结构数据,为了更好的支持动态语言调用,到 jdk13增加到17种,
表结构起始的第一位是个 u1 类型的标志位,代表当前常量属于那种常量类型:
类型 | 标志 | 描述 |
CONSTANT_Utf8_info | 1 | utf-8编码字符串 |
CONSTANT_Integer_info | 3 | 整型字面量 |
CONSTANT_Float_info | 4 | 浮点型字面量 |
CONSTANT_Long_info | 5 | 长整型字面量 |
CONSTANT_Double_info | 6 | 双精度浮点字面量 |
CONSTANT_Class_info | 7 | 类或接口字面量 |
CONSTANT_String_info | 8 | 字符串类型字面量 |
CONSTANT_Fieldref_info | 9 | 字段符号引用 |
CONSTANT_Methodref_info | 10 | 方法符号引用 |
CONSTANT_InterfaceMethodref_info | 11 | 接口方法符号引用 |
17种类型的常量数据结构汇总:
常量 | 项目 | 类型 | 描述 |
CONSTANT_Utf8_info | tag | u1 | 值为1 |
CONSTANT_Utf8_info | length | u2 | utf-8编码字符串占用字节数 |
CONSTANT_Utf8_info | bytes | u1 | 长度 length 的utf-8编码字符串 |
CONSTANT_String_info | tag | u1 | 值为8 |
CONSTANT_String_info | index | u2 | 指向字符串字面量索引 |
CONSTANT_Fieldref_info | tag | u1 | 值为9 |
CONSTANT_Fieldref_info | index | u2 | 指向声明字段的类或接口描述符CONSTANT_Class_info的索引项 |
CONSTANT_Fieldref_info | index | u2 | 指向字段描述符CONSTANT_Name_AndType的索引项 |
CONSTANT_Methodref_info | tag | u1 | 值10 |
CONSTANT_Methodref_info | index | u2 | 指向声明方法的类描述符CONSTANT_Class_info索引项 |
CONSTANT_Methodref_info | index | u2 | 指向名称及类型描述符CONSTANT_NameAndType索引项 |
CONSTANT_Class_info | tag | u1 | 值为7 |
CONSTANT_Class_info | index | u2 | 指向全限定名常量项的索引 |
查看class文件 (使用winhex工具查看)如下图
javap 命令查看字节码文件: javap -verbose j1.class