Class 类文件学习(二)

常量池

常量值存放两大类常量:

  • 字面量(Literal)
    • 如文本字符串
    • 声明为 final 的常量值等
  • 符号引用(Symbolic References)
    • 类和接口的全限定名 (Fully Qualified Name)
    • 字段的名称和描述符 (Descriptor)
    • 方法的名称和描述符

常量池的14种结构

所有constant_pool表格条目具有以下一般格式:

cp_info {
    u1 tag;
    u1 info[];
}

constant_pool表中的每个项目都 必须以一个1字节的标签开始,表明项目的种类cp_info。info数组内容随着tag数值的变化而变化。下表列出了有效标签及其值。每个标签字节必须跟有两个或多个字节,以提供有关特定常数的信息。
Class 类文件学习(二)_第1张图片
Class 类文件学习(二)_第2张图片

常量池计数器(constant_pool_count):

Class 类文件学习(二)_第3张图片

该constant_pool_count项目的值等于表中的条目数constant_pool加1。注意这里的加1,说明常量池计数器的起始值是1 而不是0。
本例常量池 0x13 换成十进制是 19 ,19-1 =18,说明本例代码有18个常量。

常量池(constant_pool []):

本例的第一个常量的tag值:
第一个tag
0x0A 为 10,查表得是

CONSTANT_Methodref_info {
    u1 tag; // 
    u2 class_index; // 指向声明方法的类描述符 CONSTANT_Class_info
    u2 name_and_type_index;// 指向名称及类型描述符 CONSTANT_NameAndType_info
}

于是第一个常量的整体内容如下:
Class 类文件学习(二)_第4张图片
class_index 为4 ,说明是指向第4个常量,name_and_type_index 指向第15 个常量,那第4、15常量在哪尼。我们得先把第2、3个常量找出来,为了后续方便,我先把所有常量的位置一步步圈出来。
第二个常量的tag值:
Class 类文件学习(二)_第5张图片
查表得tag 为9的结构如下:

CONSTANT_Fieldref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
}

Class 类文件学习(二)_第6张图片

第二个常量已经圈出来了,同理找到余下几个常量:
Class 类文件学习(二)_第7张图片
从上图看出第5、6、7的tag 都是1 ,同属于一种常量结构。查表得该结构为:

CONSTANT_Utf8_info {
    u1 tag;// 1
    u2 length;//该项的值length给出了bytes数组中的字节数(而不是结果字符串的长度)。
    u1 bytes[length];//长度为length 的utf-8编码的字符串
}

第7个常量的length 如下:
Class 类文件学习(二)_第8张图片
所以length后面的6个字节代表该常量的utf-8字符串内容。
Class 类文件学习(二)_第9张图片
继续找到余下的常量12个。
Class 类文件学习(二)_第10张图片
图(0-2)
总共18 个常量已经找完了,回过来验证刚才我们的第一个常量,看看对不对。
1。指向第4个常量,上图第4个常量 tag 是7确实是 CONSTANT_Class_info;
2。指向第15个常量 ,上图第15个常量tag 是12,对照表确实也是 CONSTANT_NameAndType_info。
结果验证我们的结果是正确的。

本例18个常量已经被我们正确的找到了,下文继续接着讲。

参考:
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4
《深入理解JAVA虚拟机.JVM高级特征与最佳实践》

你可能感兴趣的:(class)