揭开Class文件结构神秘的微笑(二)
“利用碎片化的时间,为你精讲局部知识。”
建议看完上一篇再来看这一篇
先把Class文件的表结构跑出来,回忆一下:
继续分析Class文件
访问标志:
访问标志并非简单的一个值,而是采用分位组合的值,我们根据下面这个表来判断包含了哪些值;
16进制的0021转化为二进制为0000 0000 0010 0001,可以很方便的看出由ACC_PUBLIC和ACC_SUPER组成。0020|0001=0021 通过高低位间隔设计,从而使两个字节容纳下了更多的种类,构思精巧。
本类的引用:
03指向了常量池的索引3,也就是下图中的 com/test/TestClass
父类索引:
04指向了常量池中的4索引,也就是:java/lang/Object
继承的接口个数:
00代表0个接口。所以接在本字段后面的接口表也就省略了。
类中字段个数:
00 01代表类中字段的个数是1个。那么揪下来接在这个字段之后的字段信息表就只有1个。
字段表:
下面看下字段表含有什么:
①访问标志:
和之前的类访问标志的值设定是一个道理;
0002对应的就是ACC_PRIVATE,代表这个字段是私有的。
②方法名称索引:
0005指向常量池索引5,也就是字面量:m
③字段描述符索引:
0006代表指向常量池索引6,也就是:I ,这个I代表这个字段的类型是整形int
属性个数:
0000代表0个,有可能字段会有初值之类的附加信息,会存在属性表里里面。这里属性表没有携带。
类方法个数:
0002代表该类存在2个类方法,其中有一个是编译器自动添加的方法,暂时可以不用去管。
方法表:
由于前面说明会有2个方法,故存在两个方法表;
我贴一下方法表的结构:
由于标识符、方法名称索引、方法描述索引都与字段表别无差异,所以这里不再重复了。跳过6个字节,我们看一下方法的属性表。
①方法属性个数:
0001代表含有1个属性表(备注:方法一般会把方法中的代码翻译成JVM执行的字节码,然后放置在这个属性表之中)
②方法属性表:
其实属性表的种类高达29种,由于篇幅原因,这里不再摆出来。方法属性表的名称是Code。我们来看下JVM是怎么判断的把。
接下来2个字节是:0009,指向常量池索引9,也就是Code字面量值,代表后面跟着的是Code属性表(方法属性表)
我们可以参照Code表结构进行解析了:
属性表长度:1D代表有29个字节长度。
操作数栈深度:0001,深度是1
局部变量表长度:0001,最大长度是1,也就是只含有一个局部变量。读者观察方法会发现没有局部变量,其实编译器会为我们传入this关键字对象作为本类的索引,所以会有一个默认的局部参数this。
Code字节码长度:00 00 00 05,代表有5个字符长度。
Code字节码:2A B7 00 01 B1,这些是JVM基于操作数栈的指令,这里不再细讲。
异常表数量:00 00
后面的不再细讲赘述,读者可以自己尝试一下。
尾巴:以上知识点融入了自己的理解,如果有疑问或不足,欢迎评论区或私信讨论。
参考文献:
《深入理解Java虚拟机:JVM高级特性与最佳实践(第三版)》
作者:周志明
ISBN:9787111641247