Java字节码方法表结构深度剖析

继续上一次【https://www.cnblogs.com/webor2006/p/9459681.html】的字节码分析,这次来分析一下最为复杂的方法表的信息,如下:

而上一次分析到了属性表的位置在:

接着来看一下方法表相关的信息:

所以往下找两个字节:

因为有一个编译器为其生成的一个构造方法,这时咱们对照着上一次介绍的jclasslib工具来对照一下:

接着往下则是方法表相关的信息:

先来看一下表结构:

也就是说每个方法所对应的方法表结构如上,所以接下来看一下第一个方法的信息,往下数2个字节则是access_flags,如下:

那它对应哪个访问标志则需要查一下:

表示是public的方法,接下来四个字节为方法名字和索引和描述符的索引,一起看:

其对应的常量池信息如下:

也就是第一个方法是构造方法,接着往下则是方法的属性相关的东东,注意:这个属性跟方法的变量是两码事,如下:

所以往下数两个字节,看一下方法属性的个数:

说明有一个方法属性,而往后两个字节对是属性名称索引,如下:

对应常量池:

Code属性,对于每一个方法都有一个Code属性,如下:

{
  public com.jvm.bytecode.MyTest1();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: iconst_1
         6: putfield      #2                  // Field a:I
         9: return
      LineNumberTable:
        line 3: 0
        line 4: 4
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      10     0  this   Lcom/jvm/bytecode/MyTest1;

  public int getA();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field a:I
         4: ireturn
      LineNumberTable:
        line 7: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/jvm/bytecode/MyTest1;

  public void setA(int);
    descriptor: (I)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: iload_1
         2: putfield      #2                  // Field a:I
         5: return
      LineNumberTable:
        line 11: 0
        line 12: 5
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0  this   Lcom/jvm/bytecode/MyTest1;
            0       6     1     a   I
}
SourceFile: "MyTest1.java"

其实就是描述了整个方法的Code信息,Code attribute的作用是保存该方法的结构,如所对应的字节码:

其中attribute_name_index则是属性名的索引,也就是Code,接下来还有一些信息下面来解释一下:

  • attribute_length表示attribute所包含的字节数,不包含attribute_name_index和attribute_length字段。

    说的是什么意思呢?比如attribute_length=50个字节,则是指往后的50个字节则为整个Code属性的信息,所以往后先数4个字节咱们来看一看长度:

    也就是说属性的长度为56,所以往后56个字节则为具体Code属性的信息,如下:

     那咱们来jclasslib中来确认一下是否也是显示的56个字节,如下:

  • max_stack表示这个方法运行的任何时刻所能达到的操作数栈的最大深度。

    也就是在上面56个字节从头数2个字节,则是这个操作数栈的最大深度,咱们来看一下:

    也就是最大的深度为2。如javap -verbose所示:

  • max_locals表示方法执行期间创建的局部变量的数目,包含用来表示传入的参数的局部变量。

    再继续读2个字节:

    也就是局部变量的数目为1,如javap -verbose所示:

  • code_length表示该方法所包含的字节码的字节数以及具体的指令码。具体指令码既是该方法被调用时,虚拟机所执行的字节码。

    也就是占10个字节,所以往后数10个字节:

    其实这10个字节是对应在jclasslib中的代码助记符的信息,如下:

    呃~~助记符能跟字符信息对应上?这不是扯淡么~~其实它们之间是有一些对应关系的,具体怎么对应下回再来探讨。

posted on 2018-08-19 20:36  cexo  阅读(388)  评论(0编辑  收藏  举报

导航