JVM类文件中的常量池

166 阅读2分钟

有什么作用

主要用来存放两大类常量:字面量 和 符号引用。

字面量包括以下几种:

文本字符串
8大基本数据类型
final修饰的常量

符号引用包含以下几种:

类和接口的全限定名
子段的名称和描述符
方法的名称和描述符

基本组成是什么

常量池的每一个常量都是一个表结构,由以下14个基本表结构组成

八大基本数据类型中 boolean, byte, short, int, char 都对应的是 CONSTANT_Integer_info 字段

上面的每一个类型都是一个表结构,至少包含两个字段,比如 CONSTANT_Class_info结构如下:

类型 名称 数量
u1 tag 1
u2 name_index 1

tag 就是CONSTANT_Class_info对应的标志位7
name_index 是一个索引值,因为这里需要的是类或者接口的全限定名,所以会指向一个CONSTANT_Utf8_info结构

变量,方法名最长多长,为什么?

最长65535,即64KB,因为变量,方法名都是在CONSTANT_Utf8_info中存放,该结构有三个字段:

类型 名称 数量
u1 tag 1
u2 length 1
u1 bytes length

lengh表示的是名称的长度,u2表示的是两个字节的无符号整数,最大值为65535.

代码中怎么体现出来

写一个简单的例子

/**
 * FileName : TestConstantPool.java
 * Created by zongpengq on 9/21/2018.
 */
public class TestConstantPool {
    static int intData;
    static boolean ifData;
    static char charData;
    public static void main(String[] args) {
        intData = 12;
        ifData = false;
        charData = 'a';

    }
}

javac TestConstantPool.java 得到字节码文件 TestConstantPool.class,再通过 javap -v TestConstantPool.class 可以看到代码对应的常量池部分

反编译之后发现有这段代码编译之后常量池中放有26个常量类型,简单取其中#1解释一下

#1 常量类型是 Methodref表示是一个类方法索引常量,用来描述Object的<init>方法,由类索引信息#6 和 方法索引信息 #21组成
#6 是Class类型,指向Obejct类,所以的全限定名又存放到 #26 Utf8类型中
#21 是NameAndType类型用来描述方法#13 和方法描述符信息#14
#14 用()V表示函数返回值为void