java class 文件解析 之 class 常量池 (一)

来源:互联网 发布:java报表插件 编辑:程序博客网 时间:2024/05/16 13:57

最近在看《深入理解java虚拟机》这本书,感觉还不错,写些博客来记录下学习过程(这里对应的是6.3)。

这是书上的原始  java 类,我在上面多加了一个 ina() 方法。

package org.fenixsoft.clazz;public class TestClass{private int m;public int inc(){return m+1;}public int ina(){return m+1;}}

下面看看 class 格式要求(图片是从书上copy来的):



class文件采用无符号数和表的格式来描述数据的存储方式,无符号数分为 u1,u2,u4,u8 四种,分表对应 1、2、4、8 字节,表是由无符号数或者其他的表组成的一种复合数据类型,整个class 文件就可以看成一张 表。在这里我只是简单的介绍了下,想要详细理解的同学,可以参考下其他文档资料。


class 文件对格式的要求是非常严格的,class文件的加载顺序和数量都是严格按照上图进行的。

关于这张表的各个类型我结合下面的几张图进行描述:


下面这幅图是 是经过下面命令编译: 

E:\>javac TestClass.java  

E:\>javap -verbose TestClass.class 





下面这张图是 class 文件的 16 进制文件,windows 系统 可以用 winHex 这个软件打开,



好了现在说说第一张图的字段信息吧

<1> 第一个字段(在这里我用字段描述这个名称):magic 字段 占用四个字节 这四个字节分别对应:CAFEBA BE 。这个字段是为了说明该文件能够被java虚拟机接受,没有其他作用。

<2,3> 第二个字段 和 第三个字段 说的是 jdk 所能支持的版本号,在第二张图上 可以清楚地看的到,我采用的是1.7的版本,这两个字段在 class 十六进制文件中分别对应

0000 0033 这两个字节。

分析到这里我们可以看出 class 文件的 加载时严格按照顺序进行加载的。

<4> 第四个字段 是 constant_pool_count  这个字段是描述 常量池中 常量个数,也就是接下来第五个字段的个数。细心的同学可能发现了以下的一条规律:在 表 字段类型的前面都有一个字段来描述该表的数量,在这里用的就是 constant_pool_count   来描述 constant_pool 这个字段的, 接着 class 十六进制文件 数下去,这个  constant_pool_count  对应的字节是0014  用十六进制表示十进制  是 20 。说明有 20 个常量,可是在 第二张图中却只显示了 19 个常量,这是因为第 0 项 常量 留着是由特殊考虑的,这里我们就暂时不考虑他了吧。

<5>第五个字段  constant_pool  这是常量池,在第二张图中可以看出该常量池有 19 个常量,这里需要注意的是每一个常量都对应着一张表,常量池一共有  14 种表类型。





现在开始从第一个常量池开始加载, 需要注意的是每一个常量表 都有一个  tag 字段, 占用 一个字节,该字节对应该常量的入口,本例中的第一个 入口是0A在第三张图中按顺序可以找到,0A  在十进制中是 10,在上图中 可以看到  10  对应的是  CONSTAN_Methodref_info方法引用,在第二张图中看到第一个常量是:#1 = Methodref , 指向的是#4,#16 对应 class 文件的00040010,第二个常量的入口是09,对应的是  CONSTAN_Fieldref_info  ,对应二图中的  #2 = Fieldref,指向 #3,#17对应的 class 文件的00030011。就这样一直加载完常量池的所有常量。这里我就不一一列举了,详细的可以参考书本。这里附加所有的常量表定义:


















原创粉丝点击