java的字节码详解,

java对象

public class Demo{

  private String name;
    private int num;
    
    public Demo(){
    }

    public Demo(String name1,int num1){
        name = name1;
        num = num1;
        storeData(name1,num1);
    }

    public String storeData(String name1,int num1){
    
        return name1+"----"+num1;
    }
}

java字节码

/*
        您可能会注意到仔细检查字节码,某些操作码的前缀是“a”或“i”。
        例如,在Demo类构造函数中,您可以看到aload_0和iload_2。
        前缀代表操作码正在使用的类型。
        前缀“a”表示操作码正在操作对象引用。
        前缀“i”表示操作码正在操作整数。
        其他操作码使用`b'表示字节,
        `c'表示char,'d'表示double,等等。
        此前缀可让您立即了解正在操作的数据类型。

*/


/*
        局部变量数组(也称为局部变量表)包含方法的参数,还用于保存局部变量的值。
        首先存储参数,从索引0开始。
        如果帧用于构造函数或实例方法,则引用存储在位置0.
        然后,位置1包含第一个形式参数,位置2包含第二个,依此类推。
        对于静态方法,第一个形式方法参数存储在位置0中,第二个存储在位置1中,依此类推。

        局部变量数组的大小在编译时确定,并且取决于局部变量和形式方法参数的数量和大小。
        操作数堆栈是用于推送和弹出值的LIFO堆栈。它的大小也在编译时确定。
        某些操作码指令将值压入操作数堆栈;
        其他人从堆栈中获取操作数,操纵它们并推送结果。
        操作数堆栈还用于从方法接收返回值。
*/

public class Demo {
  public Demo();
    Code:
           //位置0的第一个操作码指令aload_0将此引用推送到操作数堆栈。
           //(请记住,实例方法和构造函数的局部变量表的第一个条目是此引用。)
       0: aload_0
       
       
       //位置1的下一个操作码指令invokespecial调用该类的超类的构造函数。
       //因为所有未显式扩展任何其他类的类都隐式继承自java.lang.Object,
       //所以编译器提供必要的字节码来调用此基类构造函数。在此操作码期间,弹出操作数堆栈的最高值。
       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       
       4: return

  public Demo(java.lang.String, int);
    Code:
           
            //位置0的第一个操作码指令aload_0将此引用推送到操作数堆栈。
           //(请记住,实例方法和构造函数的局部变量表的第一个条目是此引用。)
       0: aload_0
       
       //位置1的下一个操作码指令invokespecial调用该类的超类的构造函数。
       //因为所有未显式扩展任何其他类的类都隐式继承自java.lang.Object,
       //所以编译器提供必要的字节码来调用此基类构造函数。在此操作码期间,弹出操作数堆栈的最高值。
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       
       
       //位置为4的操作码是 aload_0 和位置为1的aload_0相同
       //(请记住,实例方法和构造函数的局部变量表的第一个条目是此引用。)
       // name = name1;执行该实例方法
       4: aload_0   
       
       //此时,位置5,aload_1 操作码是指明实例方法的第一个参数变量
       5: aload_1
       
       
       //位置6 操作码指令getfield用于从对象中获取字段。
       //执行此操作码时,会弹出堆栈中的最高值。
       //然后 #2 用于构建类的运行时  常量池   的索引,其中存储了对  name1  的引用。
       //获取此引用时,它将被推送到操作数堆栈。
       
       6: putfield      #2                  // Field name:Ljava/lang/String;
       
       // num = num1;执行该实例方法
       9: aload_0
       //此时,位置9,iload_2 操作码是指明实例方法的第二个参数变量
       10: iload_2
       //位置11,操作码指令getfield用于从对象中获取字段
      11: putfield      #3                  // Field num:I
      
      
      //storeData(name1,num1);执行该实例方法   
      //位置14,的操作码aload_0
      14: aload_0
      
      //位置15,16操作码,加载对应的两个参数变量
      //storeData(name1,num1);
      15: aload_1
      16: iload_2
      
      //调用storeData(name1,num1);方法
      17: invokevirtual #4                  // Method storeData:(Ljava/lang/String;I)Ljava/lang/String;
      
      //弹出栈
      20: pop
      //返回,对于构造器,都是return;
      //对于方法带有返回值的,对象areturn;
      21: return

  public java.lang.String storeData(java.lang.String, int);
    Code:
       0: new           #5                  // class java/lang/StringBuilder
       3: dup
       4: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V
       7: aload_1
       8: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      11: ldc           #8                  // String ----
      13: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      16: iload_2
      17: invokevirtual #9                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      20: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      //返回,对于构造器,都是return;
      //对于方法带有返回值的,对象areturn;
      23: areturn
}

猜你喜欢

转载自blog.csdn.net/sinat_22988423/article/details/87558174
今日推荐