【简易JVM开发日志2】classDecode(1)解析基本信息与常量池

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

【上一篇】:https://blog.csdn.net/qq_40636117/article/details/94394949

【下一篇】:https://blog.csdn.net/qq_40636117/article/details/94654292

 

.class文件读取出字节码数据后,才算是迈出了第一步。读取出这些数据后,我们还要把这些奇奇怪怪的字节码翻译成人话才行。所以classDecode的工作就很直观了:将字节码翻译成人话

怎么翻译呢?.class文件自有一套格式,我们根据格式翻译即可。

 

一、基础信息(魔数,次版本号,主版本号)

1、魔数:前4个字节码(如下图)就是魔数了

魔数的作用就是确定这个文件是否是class文件。除了class文件外,jpg、gif文件等许多文件都有。个人觉得有点像暗号啊。

这4个字节码对应的16进制为ca fe ba be,连起来就是cafe babe(咖啡宝贝)。哈哈哈,这名字简直有毒!!

 

2、次版本号:跟着魔数的就是次版本号了(如下图)

次版本号用两位字节进行存储,即0000。对应的10进制就是0了。用于区分class版本。我不关心

 

3、主版本号:跟在次版本号后面(如下图),作用和次版本号一样,我还是不关心

 

二、常量池:常量池存放着这个类里面的数据,方法,接口等信息,是我要关心的内容了。

 

1、常量池大小:跟在主版本号后面(如下图)

和主版本号一样,也是用两个字节存储的。004f对应10进制为79。即这个常量池大小为79。

但是!常量池索引从1而不是0开始,第0个元素有特殊的意义。所以常量池实际能存放的内容为79-1=78

 

2、常量:常量池大小后面的就是常量信息了(如下图)

常量类型(tag)用一位字节进行存储。比如03代表为03常量,java规定03为Integer型常量,该常量用4个字节存储,

所以后面4个字节(00,07,a1,20)代表这个Integer类型的内容。

读取完4个字节后,下一个字节代表的是下一个常量的类型。。。。周而复始直到读够78个常量

 

在JDK1.7之前共有11种结构各异的常量类型,如下:

注明:
(1)为方便起见,字节均为10进制。
(2)u1代表1字节数据,u2代表2字节数据,以此类推
(3)cp代表常量池(ConstantPool),cp[i]代表常量池索引为i的常量

----------------------------------------------------------------------------------------
1、tag=1,代表常量是uft8,结构:
{
    u1 tag;//类型
    u2 len;//utf8长度
    u1 data[u2];//utf8内容
}
比如 1 0 6 79 98 106 101 99 116
1代表tag,即utf8;0 6这两个字节代表utf长度6(06)。
后面跟着的6个字节(79 98 106 101 99 116)即为utf8常量内容,对应utf8为Object
所以这个uft8类型的常量为Object

可惜的是,我并没有找到utf8的相关包,只能解析ascll

----------------------------------------------------------------------------------------
2、tag=3,代表类型是Integer,结构:
{
    u1 tag;//类型
    u4 val;//数值
}
比如 3 5 7 8 4,3代表这是一个Integer型,后面4位字节即这个Integer型的数值

----------------------------------------------------------------------------------------
3、tag=4,代表Float。结构同Integer

----------------------------------------------------------------------------------------
4、tag=5,代表Long,结构:
{
    u1 tag;
    u8 val;
}

----------------------------------------------------------------------------------------
5、tag=6,代表Double。结构同Long

----------------------------------------------------------------------------------------
6、tag=7,代表Class,结构:
{
    u1 tag;
    u2 index;//Class名称在常量池的索引
}
比如7 0 4。代表这是一个Class(类);而0 4这两个字节代表类名的索引为4
假设cp[4]为一个“java/lang/Object”的uft8类型,
那么这个类的名称就是java/lang/Object。

----------------------------------------------------------------------------------------
7、tag=8,代表String类型,结构和Class相同。
{
    u1 tag;
    u2 index;
}
比如8 0 4。8代表这是个String,而0 4代表index=4
假设cp[4]为“Object”(uft8类型)
那么String的内容即“Object”

从这里可以看出String本身不存放信息,它只是信息的搬运工。
到这里我也明白为啥java里面String="1234"了

----------------------------------------------------------------------------------------
8、tag=9,代表Fieldref(字段符号的引用),结构:
{
    u1 tag;
    u2 index1;//字段所属类的索引
    u2 index2;//字段名称和类型的索引
}

----------------------------------------------------------------------------------------
9、tag=10,代表Methodref(属于类的方法),结构:
{
    u1 tag;
    u2 index1;//方法所属类的索引
    u2 index2;//方法的名称和类型的索引
}
比如10 0 8 0 9,10代表这是个方法,

0 8是所属类的索引
假设常量池索引为8的常量为“java/lang/Object”,
则代表该方法属于java/lang/Object类

0 9是该方法的名称和类型索引
代表这个方法的名称和类型存放在cp[9]里

----------------------------------------------------------------------------------------
10、tag=11,代表InterfaceMethodref(属于接口的方法),结构和Methodref相同

----------------------------------------------------------------------------------------
11、tag=12,代表NameAndType(名称和类型),结构:
{
    u1 tag;
    u2 NameIndex;//名称索引
    u2 TypeIndex;//类型索引
}

比如12 0 9 0 8,代表类型为NameAndType,而Name=cp[9],Type=cp[10]




 

从上面那个表就能看出,为什么int,float,byte,char等叫做基本类型,而String,Class等叫做引用类型了。

前者直接存放数据,后者存放前者的索引,只是数据的搬运工。

 

代码太多又太杂,就不贴出来了,我们测试一下,把Object.class的常量池打印一下(部分截图)

 

——————————————————————————————————————————————————————

好了jvm的开发就告一段落了,虽然.class还有属性池辣么一大块还没解析

不过也没办法啊,毕竟有别的东西要学,不能玩物丧志啊

不能每天都来肝了,每天能抽出1~2小时继续开发都不错了。

以后的开发会越来越难,能利用的时间也越来越少了,不知道下次更新要到什么时候

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值