【简易JVM开发日志3】classDecode(2)解析属性池

【总目录/源代码】:https://blog.youkuaiyun.com/qq_40636117/article/details/94383044

【上一篇】:https://blog.youkuaiyun.com/qq_40636117/article/details/94415960

【下一篇】:https://blog.youkuaiyun.com/qq_40636117/article/details/95618443

【初遇BUG】

在开发属性池解析功能的时候遇到了开发中的第一个大BUG,那就是一些类的常量池解析出错,连带着属性池一起出现了问题(因为常量池后面就是类的访问标志,只会出现特定的数字,所以属性池解析是否异常可以看出来)。经过测试解析不同的类,发现这个错误还多种多样:

(1)有的class文件常量池和属性池解析正常。

(2)有的常量池能解析完成,但是属性池解析出错

(3)有的连常量池解析都无法正常完成,tag的值也是奇奇怪怪,甚至出现了三位数!

起初我以为是版本原因,可能某些版本解析不一样,后来对比了版本号排除了这个问题(幸好不是这个原因)

后来怀疑是某些class文件的原因,但用go版本的jvm却正常无误地解析出来。

最后没辙了,魔改作者提供的go版本虚拟机,把它解析常量池的全过程打印出来,和我的进行对比,发现居然是

。。。

long和double类型在常量池里面占两位

啊啊啊,坑死爹了,占用晚上中午和下午休息的时间,前后debug将近5,6个小时,居然是就是这么个错误!太过分了,一定要记下来!

 

【正式开发】

debug完后,后面的事情就相对简单了。

 

一、类信息(类的访问字段,本类名称,本类父类)

(1)类的访问字段(修饰符):紧跟着常量池后面的是类的访问字段,或者说修饰符(4p权限,final,interface等等)。这个访问字段用16位的数据存放起来。16位转化成16进制正好是0x0000~0xFFFF,四位数。这每一位数字都有其对应含义,或者说对应了一个修饰符。我现在还没用到,所以暂时先存放起来。

十分感谢这个修饰符,要不是它,我还发现不了解析出现了错误。

(2)本类索引:访问字段后面跟着的16位数据就是本类在常量池的索引了,没什么好说的

(3)父类索引:跟在本类索引后面,也是16位数据存储。

 

二、接口表

类除了继承一个父类外,还能实现多个接口,这些信息存放在接口表中。

和常量池一个套路,跟在父类索引后面的是接口表的大小,16位数据存储;

接口表大小后面就是若干16位数据,不用说,代表的就是这些接口在常量池里面的索引。

吐槽一下,这些接口在常量池中的类型居然是class,居然是class,居然是class,吓得我又以为解析错误了,还特地打开java源码进行求证

三、字段表,方法表

接口表后面跟着的是字段表,字段表完结后就是方法表。

之所以把这两个表放在一起讲,是因为这两个表的结构是一样的!不然我也没法开发这么快

u1:无符号1字节数据    u2:无符号2字节数据    u4:无符号4字节数据

//属性
typedef struct AttrInfo{
	u2 nameIndex;        //属性名称索引
	u4 len;              //属性内容数组大小
	u1* infos;           //属性内容数组
}AttrInfo;


字段/方法结构
//u1:无符号8位数据    u2:无符号16位数据    
typedef struct MemberInfo{
	u2 accessFlag;        //访问符
	u2 nameIndex;         //名称索引
	u2 desIndex;          //描述索引
	u2 attrCount;         //属性数组大小
	AttrInfo* attrInfos;  //属性数组(其中方法里面这里存放着方法体)
}MemberInfo;

一样的。显示这些表的大小,然后是若干个字段/方法。

 

四、其他内容

解析完方法表后,我以为解析完成了,于是输出剩下数据验证一下。没想到居然还剩下一点数据。

不过好在字段表和方法表解析正常。查阅了书本也不知道这些数据是什么意思。

虽然这些数据长短不定,不过好在并不算太多,算留下一个小尾巴,以后再说吧

 

五、结语

哎,肝了怎么就终于把.class文件(基本上)解析完成了,打印一下类信息爽一下!

 

Object.class

 

String.class

 

Double.class

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值