字节码指令解读

2021-11-12  本文已影响0人  lz做过前端

前言

我们知道JVM被称为虚拟机,它必然要有一套程序指令集,这样CPU才能和你的程序做交互,所以Java字节码指令基本可以对应到CPU的指令。
对于JVM来说,程序的执行过程就是入栈出栈的过程。在这个过程中伴随着从局部变量表存值取值,然后压栈,然后对栈内数据做计算(出栈)。此外,可以通过程序流程控制指令(改变程序计数器),达到循环、分支、跳转的效果。如果程序需要改变对象(堆),需要用到对象操作指令。如果变量类型是兼容的,编译器还会加入转换指令(基本类型)。
按照指令的性质可以把指令分为以下几类:

操作指令

栈操作指令

局部变量表操作指令

程序流程控制指令

例子:todo

对象操作指令

例子:todo

算术运算指令(执行过程会按需要的参数从操作数栈弹出数据,计算完成后压栈)

类型转换指令

调试操作指令

示例及工具使用

示例1

java代码

package cc.page.jvm.study.binarycode;
public class HelloByteCode {
    public static void main(String[] args) {
        HelloByteCode obj = new HelloByteCode();
    }
}

javap查看字节码,【】内是我对代码的解释

javap -c HelloByteCode.class
public class cc.page.jvm.study.binarycode.HelloByteCode {
  public cc.page.jvm.study.binarycode.HelloByteCode();
    Code:
       0: aload_0 【从局部变量表位置0取出值,this】
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V【todo调用常量池中位置1对应的方法,()V表示返回值为void】
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class cc/page/jvm/study/binarycode/HelloByteCode【new一个对象,参数指向常量池#2也就是HelloByteCode类地址】
       3: dup【将上面的对象压栈】
       4: invokespecial #3                  // Method "<init>":()V【调用对象方法init,返回值为void】
       7: astore_1【从栈中弹出弹出值并保存到局部变量表位置1处】
       8: return
}
注:字节码前面的数字代表在真正的字节码文件中的偏移位置,一个位置一个字节

打印局部变量表和常量池等信息
注意,常量池#1指向的应该就是常量池的标识符,值应该是存在运行时常量池中,所以应该还要去常量池

javap -c -verbose HelloByteCode.class
Classfile /Users/xuqingbin/Documents/myself/架构师进阶/workspace/jvm/target/classes/cc/page/jvm/study/binarycode/HelloByteCode.class
  Last modified 2021-11-11; size 473 bytes
  MD5 checksum 90b484786b1f7f825804e420dd281f31
  Compiled from "HelloByteCode.java"
public class cc.page.jvm.study.binarycode.HelloByteCode
  minor version: 0
  major version: 52【Java8】
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#19         // java/lang/Object."<init>":()V
   #2 = Class              #20            // cc/page/jvm/study/binarycode/HelloByteCode
   #3 = Methodref          #2.#19         // cc/page/jvm/study/binarycode/HelloByteCode."<init>":()V
   #4 = Class              #21            // java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Utf8               LineNumberTable
   #9 = Utf8               LocalVariableTable
  #10 = Utf8               this
  #11 = Utf8               Lcc/page/jvm/study/binarycode/HelloByteCode;
  #12 = Utf8               main
  #13 = Utf8               ([Ljava/lang/String;)V
  #14 = Utf8               args
  #15 = Utf8               [Ljava/lang/String;
  #16 = Utf8               obj
  #17 = Utf8               SourceFile
  #18 = Utf8               HelloByteCode.java
  #19 = NameAndType        #5:#6          // "<init>":()V
  #20 = Utf8               cc/page/jvm/study/binarycode/HelloByteCode
  #21 = Utf8               java/lang/Object
{
  public cc.page.jvm.study.binarycode.HelloByteCode();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:【代码与字节码偏移开始位置对应关系】
        line 3: 0
      LocalVariableTable:【局部变量表】
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcc/page/jvm/study/binarycode/HelloByteCode;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class cc/page/jvm/study/binarycode/HelloByteCode
         3: dup
         4: invokespecial #3                  // Method "<init>":()V
         7: astore_1
         8: return
      LineNumberTable:
        line 6: 0
        line 7: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;
            8       1     1   obj   Lcc/page/jvm/study/binarycode/HelloByteCode;
}
SourceFile: "HelloByteCode.java"

示例2

参考资料

上一篇 下一篇

猜你喜欢

热点阅读