JVM字节码指令相关

JAVA代码中的每个方法都会被编译成一系列的JVM字节码指令,这些字节码指令会被JVM所执行,从而产生相应的数据,我们通常可以用javap -verbose来查看一个方法的字节码指令。

记得自己之前写过一个简单编译器,编译之后生成的相关的指令,这写指令的编号都是连续的,因为这些指令被我存储在一个指令数组中,每次执行指令的时候,程序计数器PC就会加一,指向下一条需要执行的指令,但是我们使用javap -verbose查看方法字节码指令时,你会发现方法字节码指令前面的编号不是连续的
方法字节码指令
我们看到Lookup方法有三条字节码指令,为什么这三条字节码指令前面的编号不是0,1,2呢?

这里的编号不是以指令为单位的,而是以字节为单位。
字节码指令的结构是:
[ opcode ][ operands ]
其中opcode一定是1字节的,而operands可能是1字节、2字节、4字节或更多(如switch系指令)。
此外,方法的字节码指令都是存储在一个字节数组中的,对于aload_0前面的0表示这个字节码指令在字节数组中的偏移量是0,invokespecial前面的指令标识自己在字节数组中的偏移量是1,return表示自己在字节数组中的偏移量是4,从上面的分析可以知道invokespecial在字节数组中占据1,2,3三个下标对应的字节。

这里顺便提一下几个容易混淆的字节码指令:

  • load指令表示把局部变量区中的数据加载到操作数栈顶部
  • store指令表示把栈顶的数据存储到局部变量区中
  • invokevirtual表示调用实例的方法
  • invokespecial表示调用类的构造方法,实例初始化方法,私有方法
  • invokestatic表示调用静态方法
  • invokeinterface表示调用接口方法