常量池

主、次版本号之后的就是常量池入口,常量池可以比喻为Class文件的资源仓库,它是Class文件结构中

与其他项目关联最多的数据,通常也是占用Class文件空间最大的数据项目之一。

常量池中的常量的数量是不固定的,因此在常量池的入口需要一项u2类型的数据,代表常量池容量计数器

constant_pool_count)。这个容量不是从0开始计数,而是从1开始。因此常量的数量 = constant_pool_count - 1。

目的是让某些指向常量池的索引值的数据在特定情况下可以表达“不引用任何一个常量池项目”的含义(把索引值设置为0)。

常量池的组成

常量池中主要存放两大类常量

  • 字面量(Literal

    字面量比较接近Java语言层面的常量概念,如文本字符串、被声明为final的常量值等。

  • 符号引用(Symbolic References

    符号引用属于编译原理方面的概念,主要包括

    • 被模块导出或者开发的包(Package
    • 类和接口的全限定名(Fully Qualified Name
    • 字段的名称和描述符(Descriptor
    • 方法的名称和描述符
    • 方法句柄和方法类型(Method HandleMethod TypeInvoke Dynamic
    • 动态调用点和动态常量(Dynamically-Computed Call SiteDynamically-Computed Constant

Class文件中不会保存各个方法、字段最终在内存中的布局信息,这些字段、方法的符号引用不经过虚拟机

在运行期转换的话是无法得到真正的内存入口地址的,当虚拟机做类加载时,将会从常量池获得对应的符号引用,

再在类创建时或运行时解析、翻译到具体的内存地址中。

常量池中的每一项都是一个表,表结构起始的第一个位是个u1类型的标志位(tag),代表着当前常量属于

哪种常量类型。(每个表的结构都不一样)

ps

Class文件中方法、字段等都需要引用CONSTANT_Utf8_info型常量来描述名称。所以CONSTANT_Utf8_info型常量

的最大长度就是Java中方法、字段名的最大长度。这里最大长度就是length 的最大值,既u2类型能表达的最大值

65535。所以Java程序无法定义超过64KB英文字符的变量或方法,会无法编译。