紧接着主、次版本号的是常量池入口,常量池入口需要放置一项 u2 类型的数据,代表常量池容量计数值(constant_pool_count),这个容量计数是从 1 而不是从 0 开始,第 0 项用于表达“不引用任何一个常量池项目”的含义。Class 文件结构中只有常量池的容量计数是从 1 开始,其他都是从 0 开始。
常量池中主要存放两大类常量:字面量和符号引用。字面量比较接近 Java 语言层面的常量概念,如文本字符串、被声明为 final 的常量值等。而符号引用则属于编译原理方面的概念,主要包括下面几类常量:
被模块导出或开放的包(Package)
类和接口的全限定名(Fully Qualified Name)
字段的名称和描述符(Descriptor)
方法的名称和描述符
方法句柄和方法类型(Method Handle、Method Type、Invoke Dynamic)
动态调用点和动态常量(Dynamically-Computed Call Site、Dynamically-Computed Constant)
Java 会在虚拟机加载 Class 文件的时候进行动态连接,将符号引用转换为真正的内存入口。常量池中每一项常量都是一个表,最初有 11 种结构不同的表结构数据,后来为了更好地支持动态语言调用,额外增加了 4 种动态语言相关的常量,后来为了支持 Java 模块化,又加入了 2 个常量,所以截止 JDK13,常量表中有 17 种不同类型的常量。这 17 类表都有一个共同的特点,表结构起始的第一位是个 u1 类型的标志位(tag)
17 种常量类型所代表的具体含义如表:
类型 标志 描述
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 接口中方法的符号引用
CONSTANT_NameAndType_info 12 字段或方法的部分符号引用
CONSTANT_MethodHandle_info 15 表示方法句柄
CONSTANT_MethodType_info 16 表示方法类型
CONSTANT_Dynamic_info 17 表示一个动态计算常量
CONSTANT_InvokeDynamic_info 18 表示一个动态方法调用点
CONSTANT_Moudle_info 19 表示一个模块
CONSTANT_Package_info 20 表示一个模块中开放或者导出的包