路人战队|授人以鱼不如授人以渔,软妹手把手教你javap反编译分解代码( 三 )


添加一个方法时 , 常量池中会增加4个常量;同理 , 添加字段也是如此 , 添加的内容有:
CONSTANT_Methodref_info方法的符号引用方法符号引用指向的CONSTANT_NameAndType_info方法的部分符号引用方法的名称方法的描述符紧接着常量池之后的两个字节代表访问标志(access_flags) , 用于识别一些类或者接口层次的访问信息 , 包括:这个Class是类还是接口、是否为public类型、是否为abstract类型、类是否声名为final等 。 标志位及其含义如下表:
路人战队|授人以鱼不如授人以渔,软妹手把手教你javap反编译分解代码
文章图片
TestJVM这个类仅仅被public修饰了 , 因此其他的标志都为假 , 最终access_flags应为0x0001|0x0020=0x0021 , 字节码中值内容确实是这个 。
路人战队|授人以鱼不如授人以渔,软妹手把手教你javap反编译分解代码
文章图片
访问标志之后顺序排列类索引(this)、父类索引(super)、接口索引集合(interfaces) 。 Class文件由这三项来确定这个类的集成关系 。
路人战队|授人以鱼不如授人以渔,软妹手把手教你javap反编译分解代码
文章图片
类索引和父类索引引用2个u2类型的索引值表示 , 他们各自指向一个类型为CONSTANT_Class_info的类描述符常量 , 通过CONSTANT_Class_info类型的常量中的索引值找到定义在CONSTANT_Utf8_info类型的常量中的全限定名字符串 , 从而找到类 。
类索引和父类索引都是u2类型的数据 。
路人战队|授人以鱼不如授人以渔,软妹手把手教你javap反编译分解代码
文章图片
JAVAP里面看到的这两个索引 , 分别是此类继承自Object基类 , 就无别的继承关系了 。
路人战队|授人以鱼不如授人以渔,软妹手把手教你javap反编译分解代码
文章图片
接口索引集合入口第一项是u2类型的接口计数器(interfaces_count)表示索引表的容量(即实现了几个接口) 。 如果该类没有实现任何接口 , 则计数器值为0 , 后面的接口索引表不再占用任何字节 , 0x0000因为此类没有实现任何接口 。看到这里已经很累了吧 , 我写的都累了 , 安利给读者们一首小阿七的歌《不谓侠》 , 很好听啊~
接口索引集合后边的是字段计数器:用于标识有多少个字段 , 接着就是字段表集合 。 字段表(field_info)用于描述接口或者类中声明的变量 。
字段包括类级变量以及实例级变量 。 可以包括的信息有:
字段的作用域(public、private、protected修饰符)实例变量还是类变量(static修饰符)可变性(final)并发可见性(volatile)可否被序列化(transient)字段数据类型(基本类型 , 对象 , 数组)字段名称各个修饰符都是布尔值 , 要么有要么没有 , 这个可以使用标志位表示;但字段叫什么名字、字段被定义成什么类型 , 都是无法固定的 , 所以只能引用常量池中的常量来描述 。 由字段的这些内容信息 , 抽象得到如下的字段表结构:
路人战队|授人以鱼不如授人以渔,软妹手把手教你javap反编译分解代码
文章图片
name_index和descriptor_index都是对常量池的引用 , 分别代表着字段的简单名称以及字段和方法的描述符 , 关于全限定名、简单名称及描述符的区别:
全限定名ai/yunxi/vm/TestClasss类的全限定名,仅仅是把类中的“.”替换成了“/”
简单名称没有类型和参数修饰的方法或者字段名称如:add()和intm简单名称就是:add、m
描述符用来描述字段的数据类型、方法的参数列表(数量、类型及顺序)和返回值
路人战队|授人以鱼不如授人以渔,软妹手把手教你javap反编译分解代码
文章图片
字节码中0x0002代表字段为private , 字节码代表如下:
u20x0002->第一个跟着的是fields_count,这个类只有2个字段表数据以下是字段表内容:u20x0002private为真 , 其他为假u20x000a字段名称name_index,由上面JAVAP常量表可知#10为au20x000b字段描述符descriptor_index,由上面JAVAP常量表可知#11指向常量池字符串I , 这个描述符标识字符含义标识基本类型intu20x0000attribute_count属性表集合无属性 , 为0表示没有额外描述的信息attribute_info上面无内容 , 不占字节复制代码描述符标识字符含义 , 上面的标识基本类型为I , 即对应的下面表的基本类型int