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中的代码助记符的信息,如下:
呃~~助记符能跟字符信息对应上?这不是扯淡么~~其实它们之间是有一些对应关系的,具体怎么对应下回再来探讨。