字节码

魔数

字节码开头的4个字符(U4)表述魔数,魔数为固定值ca fe ba be

 字节码

大小版本

Jdk版本如1.8.x,x就表示jdk的小版本,小版本是紧跟着魔数后的两个字节U2,大版本是紧跟在小版本后的两个字节U2,如1.8

 字节码

16进制的34转化为10进制为52,对应java大版本为1.8

常量池

紧跟在版本后面的U2表示常量池数量,18表示有23个常量(24-1)

 字节码

常量池后紧跟常量,每个常量开始都有一个U1,表示常量的类型,常量类型有如下几种:

 字节码

以第一个常量为例子

 字节码

0a表示类型为10(CONSTANT_Methodref)的常量,0004表示名称在常量池的索引,0014表示描述符在常量池的索引

 字节码

访问修饰符

紧跟在常量池之后的是访问修饰符U2:

名称

字节码

含义

ACC_PUBLIC

0x0001

公开

ACC_PRIVATE

0x0002

私有

ACC_PROTECTED

0x0004

protected

ACC_STATIC

0x0008

静态

ACC_FINAL

0x0010

Final

ACC_SYNCHRONIZED

0x0020

同步

ACC_VOLATILE

0x0040

volatile

ACC_TRANSIENT

0x0080

不需要序列化

ACC_NATIVE

0x0100

native

ACC_INTERFACE

0x0200

接口

ACC_ABSTRACT

0x0400

抽象

ACC_STRICT

0x0800

strictfp

ACC_SUPER

0x0020

超类

 字节码

表示ACC_PUBLIC+ ACC_SUPER公开的存在超类的

This_Class

访问修饰符之后的U2,表示this类在常量池中的索引

 字节码

 

 

 字节码

Supper_Class

This_Class之后的U2,表示supperClass在常量池中的索引

 字节码

 

 

 字节码

Interface-count

紧跟这supper_Class之后的U2,表示接口数量

 字节码

表示存在1个接口,接口后的U2表示接口在常量池中的索引

 字节码

Fields

接口之后的U2,表示属性数量

 字节码

Fields池

属性之后紧跟属性池,属性池属性如下

访问修饰符

每个属性的一个U2表示属性修饰符

 字节码

表示ACC_PRIVATE,私有的

属性名索引

访问修饰符之后的U2,表示属性名在常量池中的索引

 字节码

 

 

 字节码

属性描述符索引

属性名索引之后的U2表示属性描述符索引

 字节码

 

 

 字节码

Field_attributes_count

属性描述符之后的U2,表示Field_attributes_count

 字节码

表示没有Field_attributes

methods_count

属性之后的U2,表示方法数量

 字节码

表示存在三个方法

method_info

紧跟在方法数量后面的,是具体的方法信息

com.sun.org.apache.bcel.internal.Constants封装了相应的助记符信息

访问修饰符

每个方法信息的第一个U2,表示方法的访问修饰符

 字节码

表示ACC_PUBLIC,公开的

方法名索引

紧跟在访问修饰符之后的U2,表示方法名在常量池中的索引

 字节码

 

 

 字节码

方法描述索引

紧跟在方法名索引后的U2,表示方法描述在常量池中的索引

 字节码

 

 

 字节码

attributes_count

紧跟在方法描述索引后的U2,表示attributes_count数量信息

 字节码

表示attributes_count的数量为1

attributes_info

紧跟在attributes_count之后的是具体attribute信息

 

Code_attribute {  //Code_attribute包含某个方法、实例初始化方法、类或接口初始化方法的Java虚拟机指令及相关辅助信息

  u2  attribute_name_index;  0007       Code

  u4  attribute_length;    0000002F      47

  u2  max_stack;       0001        1 //用来给出当前方法的操作数栈在方法执行的任何时间点的最大深度

  u2  max_locals;      0001         1 //用来给出分配在当前方法引用的局部变量表中的局部变量个数

  u4  code_length;      00000005      5 //给出当前方法code[]数组的字节数

  u1  code[code_length];    2AB70008 B1    42、183、0、8、177 

        //给出了实现当前方法的Java虚拟机代码的实际字节内容 (这些数字代码实际对应一些Java虚拟机的指令)

  u2  exception_table_lentgh;   0000       0          //异常的信息

  {

    u2  start_pc;   //这两项的值表明了异常处理器在code[]中的有效范围,即异常处理器x应满足:start_pc≤x≤end_pc

    u2  end_pc;   //start_pc必须在code[]中取值,end_pc要么在code[]中取值,要么等于code_length的值

    u2  handler_pc; //表示一个异常处理器的起点

    u2  catch_type; //表示当前异常处理器需要捕捉的异常类型。为0,则都调用该异常处理器,可用来实现finally。

  } exception_table[exception_table_lentgh];      在本类中大括号里的结构为空

  u2  attribute_count;    0002          2    表示该方法的其它附加属性,本类有1个

  attribute_info  attributes[attributes_count];       000A、000B     LineNumberTable、LocalVariableTable

}

 

attribute_name_index

每个attributes_info,的第一个U2,表示attributes_name_index

 字节码

 

 

 字节码

attribute_length

紧跟之后的U4来表示

 字节码

表示后面的2*16+15=47个长度为attribute_length

 字节码

max_stack

紧跟之后的U2,用来给出当前方法的操作数栈在方法执行的任何时间点的最大深度

 字节码

当前方法的操作数栈在方法执行的任何时间点的最大深度为1

max_locals

紧跟之后的U2,用来给出分配在当前方法引用的局部变量表中的局部变量个数

 字节码

当前方法引用的局部变量表中局部变量数量为1,为this

code_length

紧跟之后的U4,表示给出当前方法code[]数组的字节数

 字节码

当前方法的code[]数组字节数为5

 

2a表示

 字节码

B7表示invokespecial,0001,表示参数索引

 字节码

B1表示return

exception_table_lentgh

{

    u2  start_pc;   //这两项的值表明了异常处理器在code[]中的有效范围,即异常处理器x应满足:start_pc≤x≤end_pc

    u2  end_pc;   //start_pc必须在code[]中取值,end_pc要么在code[]中取值,要么等于code_length的值

    u2  handler_pc; //表示一个异常处理器的起点

    u2  catch_type; //表示当前异常处理器需要捕捉的异常类型。为0,则都调用该异常处理器,可用来实现finally。

  }异常表属性

 

紧跟之后的U2,表示异常表长度

 字节码

表示没有异常信息

code_ attribute_count

紧跟其后的U2,表示code_attribute数量

 字节码

表示存在两个属性信息

LineNumberTable和LocalVariableTable又是两个预定义的attribute,其结构如下:

LineNumberTable_attribute { //被调试器用来确定源文件中由给定的行号所表示的内容,对应于Java虚拟机code[]数组的哪部分

  u2  attribute_name_index;      000A

  u4  attribute_length;          00000006

  u2  line_number_table_length;     0001

  {  u2  start_pc;          0000    

     u2  line_number;         0004     //该值必须与源文件中对应的行号相匹配

  } line_number_table[line_number_table_length];

}

以及:

LocalVariableTable_attribute {

  u2  attribute_name_index;    000B

  u4  attribute_length;        0000000C

  u2  local_variable_table_length;   0001

  {  u2  start_pc;          0000

     u2  length;           0005

     u2  name_index;       000C

     u2  descriptor_index;    000D    //用来表示源程序中局部变量类型的字段描述符

    u2   index;          0000

  } local_variable_table[local_variable_table_length];

然后就是第二个方法,具体略过。

attributes_count

紧跟之后的U2是file_attributes_count

 字节码

表示有一个属性

attributes_info

SourceFile_attribute {

  u2  attribute_name_index;  0017     SourceFile

  u4  attribute_length;      00000002   2

  u2  sourcefile_index;        0018     ByteCodeTest.java //表示本class文件是由ByteCodeTest.java编译来的

}

attribute_name_index

U2

0012表示fileAttribute名称索引

 字节码

attribute_length

U4

 

sourcefile_index

U2

 字节码

上一篇:reduce 累加器


下一篇:ES6 之reduce的高级技巧