美文网首页
简单的main方法字节码学习

简单的main方法字节码学习

作者: 上重楼 | 来源:发表于2018-05-11 11:11 被阅读65次

    java源码如下:

       public static void main(String[] args) {
           int a = 10;
           int b = 1000;
           System.out.println(add(a, b));
       }
    
       public static int add(int a, int b) {
           int c = a + b;
           return c;
       }
    

    解析字节码后:

    public class Taaa {
     public Taaa();
       Code:
          0: aload_0    //将局部变量表0号位置(this)入栈  实例方法局部变量表的第一个元素一定是对象的引用(this)
          1: invokespecial #1              // Method java/lang/Object."<init>":()V 调用私有的实例化方法
          4: return
    
     public static void main(java.lang.String[]);
       Code:
          0: bipush        10                  //将操作数10转为int类型入栈,就是源码里的变量a
          2: istore_1                            //将操作数栈 栈顶元素加载到局部变量表索引为1的这个位置
          3: sipush        1000              //将操作数1000转int 入栈,源码里的b
          6: istore_2                           //同 istore_1  只是索引为2
          7: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream; 将运行时常量池的#2元素入栈
         10: iload_1                          //读取局部变量表元素1到栈顶
         11: iload_2                           //读取局部变量表元素2到栈顶
         12: invokestatic  #3                  // Method add:(II)I  调用静态方法add
         15: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V 调用输出 
         18: return
    
     public static int add(int, int);
       Code:
          0: iload_0     //在add这个方法里面,有一个新的局部变量和新的操作数栈,所以源码里的a和b分别作为局部变量表的0和1元素,这行是加载第0个元素到栈顶
          1: iload_1   //这行是加载第1个元素到栈顶
          2: iadd       //将栈的最前面2个元素相加 将结果入栈(栈顶)
          3: istore_2  //将栈顶元素存入局部变量表第2个位置
          4: iload_2   //读取局部变量表第2个位置的元素加载到栈顶
          5: ireturn   //返回栈顶的int类型数据
    }
    

    这里有几个小细节,在源码同样都是int类型的 a 和b 在字节码分别用 bipush sipush载入。说明源码里的值被按照其取值范围窄化为小类型了。

    局部变量表和操作数栈在每个方法被调用的时候创建,方法的参数顺序就是加入到局部变量表的顺序,比如add方法,a存在局部变量表的0位置,b存在1位置

    每一行字节码开头的数值是本行相对于方法起始处的字节偏移量

    静态方法局部变量表从0开始,方法的入参依次存入。
    实例方法局部变量表从1开始,方法的入参从1开始存。0存了对象的引用

    add方法偏移3、4那2行, 先将计算结果从栈顶存入局部变量表,又从局部变量表加载到栈顶,然后才返回栈顶。看上去是在重复计算,是因为源码没有直接 return a+b;
    而这个字节码还没经过jvm的优化,只是完完全全的翻译源代码。所以写代码的时候尽量简单点。

    相关文章

      网友评论

          本文标题:简单的main方法字节码学习

          本文链接:https://www.haomeiwen.com/subject/bbxfdftx.html