定义数组时的字节码简单分析

103 阅读2分钟

在查看下案例字节码时,对stack大小为何为4有过疑惑

public class TestClassFile {
    public void add() {
        int[] arr={1,2,3};
        int i=arr[0]+arr[1];
    }
}

字节码如下

    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=4, locals=3, args_size=1
         0: iconst_3
         1: newarray       int
         3: dup
         4: iconst_0
         5: iconst_1
         6: iastore
         7: dup
         8: iconst_1
         9: iconst_2
        10: iastore
        11: dup
        12: iconst_2
        13: iconst_3
        14: iastore
        15: astore_1
        16: aload_1
        17: iconst_0
        18: iaload
        19: aload_1
        20: iconst_1
        21: iaload
        22: iadd
        23: istore_2
        24: return
      LineNumberTable:
        line 5: 0
        line 6: 16
        line 7: 24
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      25     0  this   Lchapter_6/TestClassFile;
           16       9     1   arr   [I
           24       1     2     i   I

一开始以为是下方的加法运算造成的,但是分析后实际上加法运算只会使用两个栈空间,那么问题就出在一开始的数组定义上了。

实际上,数组在字节码中创建的过程如下:

  1. 数组长度入栈
  2. 数组指针入栈
  3. 数组index入栈
  4. 数组在该index下的值入栈
  5. 将值储存到数组index的位置,index与index下的值出栈,如果index<length,返回3;否则结束数组创建

在字节码中对应的是

    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=4, locals=3, args_size=1
         0: iconst_3               //数组长度
         1: newarray       int     //创建数组
         3: dup              
         4: iconst_0               //index=0
         5: iconst_1               //arr[0]的值为1
         6: iastore                //储存
         7: dup
         8: iconst_1               //index=1
         9: iconst_2               //arr[1]的值为2
        10: iastore                //储存
        11: dup
        12: iconst_2               //index=2
        13: iconst_3               //arr[2]的值为3
        14: iastore                //储存
        15: astore_1
        16: aload_1
        17: iconst_0
        18: iaload
        19: aload_1
        20: iconst_1
        21: iaload
        22: iadd
        23: istore_2
        24: return
      LineNumberTable:
        line 5: 0
        line 6: 16
        line 7: 24
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      25     0  this   Lchapter_6/TestClassFile;
           16       9     1   arr   [I
           24       1     2     i   I