$2.3、我就是反编译器,走进字节码世界

按照我们上篇生成的字节码文件解析与组成部分,现在我们要挨个读取里面的内容,真正走进字节码文件的世界

$2.3、我就是反编译器,走进字节码世界

模数:四个字节(1个字节占8位,其中16进制刚好4位代表,因此2个16进制就是代表1个字节)CAFE BABE,Java之父定义的固定值,没有啥好说的。

版本号:00 00 00 34,代表的版本号就是52,其中次版本号没有,JDK1.8对应的主版本号就是52,JDK1.7就是51,依次递减

常量池信息(u2个数+常量表n)00 18代表的个数是 24-1=23个,因此后续的常量表只要算对应的23个常量表即可

常量表(u1代表的都是tag信息,具体tag所代表的常量类型则是由规范定义):

  1. 0A代表的十进制是10,后续有2个常量信息,分别的长度是u2,00 04,00 14而且根据规范所代表的都指向常量索引,分别是4号和20号索引,具体表示的内容为什么方法的类描述信息、名称和类型的信息,我们从idea验证中可以得到:$2.3、我就是反编译器,走进字节码世界显然我们翻译过来应该就是object类的构造方法。
  2. 09 00 03 00 15-->代表tag等于9对应的描述,分别指向3号和21号索引,代表的意思什么字段的类或者接口信息、字段的描述符信息;其实就是字段所属的类或者接口,同时字段本身的名称和类型,我们查看下对应的2号常量信息$2.3、我就是反编译器,走进字节码世界见名思意,字段索引,所属的类是jp.zhang.bytecode.MyTest1,对应的名称是a,对应的类型是Int类型。
  3. 07 00 16-->代表tag是等于7,后面只有一个u2信息代表指向全限定名的常量索引,所指向的常量号为22,代表的就是类的全限定名(类路径)$2.3、我就是反编译器,走进字节码世界
  4. 07 00 17-->跟以上类似,只是指向的常量池号为23$2.3、我就是反编译器,走进字节码世界
  5. 01 00 01 61 -->读取tag为1的常量信息,一个u2代表的是utf-8字符串的长度,后续的u1代表的长度对应的字符串,16进制61代表的字符串就是a
  6. 01 00 01 49-->跟上述类似,49代表的就是I$2.3、我就是反编译器,走进字节码世界
  7. 01 00 06 3C 69 6E 69 74 3E-->因为代表的长度是6位,因此后续读取6位,那么对应的字符串信息就是<init>方法,这个方法代表的就是类的空参构造方法
  8. 后续的常量池信息以此类推了,根据tag的值和相对应的读取对应的字节数长度即可。

类的访问困控制权限(u2长度):00 21-->它是由对应的权限并集产生,因此是由$2.3、我就是反编译器,走进字节码世界

跟我们IDEA验证的对比(jdk1.0.2之后acc_super都必须为真)$2.3、我就是反编译器,走进字节码世界

类名(u2):00 03,指向3号常量,按照我们上面常量的解析,对应的3号为MyTest1

父类名(u2):00 04 按照上述的解析,对应的父类是Object

接口个数(u2):00 00,没有实现的接口

接口名(n,与接口个数有关):因为上述接口个数为0,因此该项也不存在。

字段个数(u2)00 01,代表的类中字段只有一个

字段表(n)根据上述字段的个数,依次解析对应的字段信息,其中字段表的组成为$2.3、我就是反编译器,走进字节码世界

00 02 00 05 00 06 00 00这就是字段表的具体信息,0002对应的访问权限为private,对应的字段名称是5号索引a,对应的描述信息是6号索引I,也就是Int类型,后续为0即没有别的属性数量,从这些信息中,其实就已经得知对应在代码中的表现形式了:private int a (完全是通过对字节码文件的解析的出来的)

方法个数(u2)00 03代表的是该类中存在三个方法,其实就是getA(),setA(int a)和空参构造init方法

方法表:跟字段表类似,它的方法表的组成结构为$2.3、我就是反编译器,走进字节码世界

00 01 00 07 00 08 00 01-->方法方法对应的权限0001是public,方法对应的名称0007对应的是7号索引init(空参构造方法),0008对应的描述信息是指向8号索引()V,方法是空参的构造方法,