关于静态常量池
.class文件中的常量池 ( Constant Pool ) 也叫做静态常量池,是存放常量数据的地方。
熟悉c/c++的人可能对于常量第一反应是:constan修饰的变量,但是在此处提到的常量范围更加广泛一些,在java中提到的常量是指:在运行中所有不会再发生变化的数据。比如类的名字、方法的名字、方法所属的类、方法的参数、方法的返回值类型、定义的常量(也就是c/c++中的const修饰的变量),所以可以发现,这个常量池里存放的数据非常的丰富。
这一部分很重要,里面的常量项会在后续的方法表、字段表等地方大量被引用。
1、常量池存放的内容
常量池中主要存放两大类型常量项:字面量(literal)与符号引用(symbolic references)
1、字面量:由字符、数字等构成的字符串或者数值统称为字面量,并且字面量必须作为右值出现(即等号右边的值)
比如:int a = 123;String s = “hollis”;
123和"hollis"就被称为字面量。
2、符号引用:用一组符号来描述所引用的目标,符号引用的内容可以是任意形式的字面量,只要能根据符号引用精确的定位到目标即可。当使用javac将java程序编译成.class文件时,.class文件并无法知道方法、字段在内存中的最终布局(因为还没有被JVM后期编译),此时在.class文件中就需要将这些的方法、字段用符号引用代替真正的内存地址,直到类加载的解析阶段再用直接引用替换掉符号引用。
符号引用主要包括三类:类和接口的全限定名、字段的名称和描述、方法的名称和描述符
常量池项的细化和分类:
将常量池与常量项图形化后如下:
注意:
图中可以看出,常量项#0为预留,.class文件规范中提到过:“指向#0表示不知向常量池任何一项”。所以constant_pool_pool - 1才是有效常量项的数量,有效常量项是从#1开始的,最后一个有效常量项为constant_pool_count - 1
Javap反编译后的静态常量池截图示例,后面会有专门的代码和constant pool进行分析:
2、常量池各个项目类型(cp_info)详解
常量池中的每一个常量项都可以当作一张表,这些表都具有一个特点,就是表的第一个字节是用来声明该常量项的标志位,表示当前常量项属于哪个类型,见下表:
类型 | 标志 |
---|---|
CONSTANT_Utf8_info | 1 |
CONSTANT_Integer_info | 3 |
CONSTANT_Float_info | 4 |
CONSTANT_Long_info | 5 |
CONSTANT_Double_in |