JVM 进阶 (十九)——Class 文件常量池
在上一博文《JVM进阶(十八)——初识Class文件》中,我们了解了 Class 文件的一些基础知识。他的整个内部结构就是一张很大的表,我们就是从这张表入手,一一分析每个部分的结构。继续看这张表:
接着上一博文所说,魔数后面分别是次版本号和主版本号。由上图可知其分别占用两个字节。
被蓝色框框住的就是次版本号,划红线的就是主版本号。再次说明,Class 文件内部的数据是按照规则紧凑排列的,中间不会有空隙。
接下来就是说明常量的个数了。代表着常量池中有多少个常量,由于常量池中的常量数量不确定,所以才会有这个数据项。依然看上图可知该数据项是占用 2 个字节,因此顺着主版本号往后面数两个字节得到:0x002E
(16 进制),即十进制的 51,也就是说常量池中有 50 项常量,索引从 1 到 50。
这里所指的常量与JAVA
代码中所说的常量有所不同,这里的常量主要包括字面量和符号引用,这两个概念很好理解。
字面量跟 JAVA 代码中的常量概念类似,如字符串、常量的值等等。
符号引用指的是类与接口的全限定名、字段、方法的名词和描述符。可以暂时理解为类、接口、字段、方法的名字。这里我们来回忆一下类加载机制中的解析阶段:他是将符号引用转化为直接引用。直接引用指的就是可以直接指向目标的指针。可以粗略的理解为:符号引用只是用一些符号来描述他要引用的目标,而直接引用才是真正的指向了他要引用的目标。
在常量池中的每个数据项都是以表的形式存在的,这里每个表都会有一个标志位 tag,来说明自己的是哪一类型的数据。如图:
我们来看下面的代码:
根据以上知识和代码,我们继续来看看Class
文件接下来的数据。紧接着常量池数量之后的便是常量表了。刚刚也说了,每个表都会有一个一个字节的标志位,那么常量池数量0x002E
之后一个字节便是0x0A
,这个就是标志位,十进制是 10,查表可知是个方法的符号引用。他的表结构如下:
因此后面还有 4 个字节是属于该表的,我们接着看是0x000B
和0x001C
,也就是说他的CONSTANT_Class_info
索引项是 11;CONSTANT_NameAndType
的索引项是 28,也就是常量池中第 11 项常量和 28 项常量,我们这里就通过工具来看了。找到第 11 项常量,查看 11 项常量的表结构,继续使用刚刚那样的寻找方法,一直找到标志位为 1 的常量项,也就是CONSTANT_Utf8_info
的表结构,这样就可以得出我们最开始查看的那个表结构的一些具体信息了。
如果觉得查看过程繁琐,可以采用javap -verbose Main
来查看:
如上图:第 1 项有指向第 11 和 28 项的索引,他们的值分别是后面的字符串,代表的是一个默认的空的构造函数。
查看跟踪的过程比较枯燥无味,但这也是我们深入了解虚拟机的一个非常重要的基础,大家可查阅更多的相关资料进行学习,有困难,迎难而上才会成长!
版权声明: 本文为 InfoQ 作者【No Silver Bullet】的原创文章。
原文链接:【http://xie.infoq.cn/article/45cd2a379cbaa9bc03e0776b3】。文章转载请联系作者。
评论