局部变量表
局部变量表(Local Variable Table)是一组变量值存储空间,用于存放方法参数和方法内定义的局部变量。
一个局部变量可以保存一个类型为boolean、byte、char、short、int、float、reference和returnAddress类型的数据。reference类型表示对一个对象实例的引用。
第1个位置问题
非静态函数
从istore_1开始
istore_0 = this
静态函数
从istore_0开始
操作数栈
操作数栈(Operand Stack)也常称为操作栈,它是一个后入先出栈(LIFO)。同局部变量表一样,操作数栈的最大深度也在编译的时候写入到方法的Code属性的max_stacks数据项中
当一个方法刚刚开始执行时,其操作数栈是空的,随着方法执行和字节码指令的执行,会从局部变量表或对象实例的字段中复制常量或变量写入到操作数栈,再随着计算的进行将栈中元素出栈到局部变量表或者返回给方法调用者,也就是出栈/入栈操作。一个完整的方法执行期间往往包含多个这样出栈/入栈的过程。
iconst
当int取值 -128~127 时,JVM采用 bipush 指令将常量压入栈中
-1至5
当int取值-1~5时,JVM采用iconst指令将常量压入栈中
int 取值 0~5 时,JVM采用 iconst_0、iconst_1、iconst_2、iconst_3、iconst_4、iconst_5指令将常量压入栈中;
取值-1时,采用iconst_m1指令将常量压入栈中
public int getInt1(){
int af1 = -1; // iconst_m1
int a0 = 0; // iconst_0
int a1 = 1;
int a2 = 2;
int a3 = 3;
int a4 = 4;
int a5 = 5;
return 10;
}
add 例子1
public int add(){
int a = -1;
int b = 3;
return a+b;
}
public int add();
Code:
0: iconst_m1 //常量-1加载到操作数栈
1: istore_1 // 将-1从操作数栈存储到局部变量表 第2个位置
2: iconst_3 //常量3加载到操作数栈
3: istore_2 // 将常量3从操作数栈存储到局部变量表 第3个位置
4: iload_1 // 加载局部变量第1个变量压入操作数栈
5: iload_2 // 加载局部变量第2个变量压入操作数栈
6: iadd // 操作数栈中的前两个变量相加,并将结果压入操作数栈顶
7: ireturn // 返回
add 例子2
public int add1(){
int a = 5;
int b = 6;
return a+b;
}
public int add1();
Code:
0: iconst_5 // 常量5加载到操作数栈
1: istore_1 // 将5从操作数栈存储到局部变量表 第2个位置
2: bipush 6 // 常量6加载到操作数栈
4: istore_2 // 将6从操作数栈存储到局部变量表 第3个位置
5: iload_1 // 加载局部变量第1个变量压入操作数栈
6: iload_2 // 加载局部变量第1个变量压入操作数栈
7: iadd // 操作数栈中的前两个变量相加,并将结果压入操作数栈顶
8: ireturn // 返回
iload
非静态方法
从iload_1开始的,默认第iload_0是this
public int getSize1(int a,int b){
int result = a +b+ 10;
return result;
}
public int getSize1(int, int);
descriptor: (II)I
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=3
0: iload_1 // 从iload_1开始 iload_0是this
1: iload_2
2: iadd
3: bipush 10
5: iadd
6: istore_3 //0:this 1:a 2:b 3:result
7: iload_3
8: ireturn
静态方法
从iload_0开始的
public static int getStaticSize(int a,int b){
int result = a +b+ 10;
return result;
}
public static int getStaticSize(int, int);
descriptor: (II)I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=2
0: iload_0 // 从iload_0开始
1: iload_1
2: iadd
3: bipush 10
5: iadd
6: istore_2 //0:a 1:b 2:result
7: iload_2
8: ireturn
多种类型demo
int size = 20;
int MAX = 100;
public int add(int a){
int result = a +size+ 10 + MAX;
return result;
}
public int add(int);
descriptor: (I)I
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=2
0: iload_1 // 从局部变量第1个位置加载到操作数栈顶
1: aload_0 // 把 this 装载到操作数栈顶
2: getfield #3 // Field size:I 将栈顶的指定的对象的第 4 个实例域(Field)的值,压入栈顶。#3 就是指的我们的成员变量size
5: iadd // a+this.size 并将结果压入操作数栈顶
6: bipush 10 // 将常量10压入操作数栈顶
8: iadd // 上1个iadd的结果集和10相加 并将结果压入操作数栈顶
9: aload_0 // 把 this 装载到操作数栈顶
10: getfield #5 // Field MAX:I 将栈顶的指定的对象的第 6 个实例域(Field)的值,压入栈顶。#5 就是指的我们的成员变量MAX
13: iadd // 上1个iadd的结果集和this.MAX相加 并将结果压入操作数栈顶
14: istore_2 // 把result放到具备变量的第3个位置
15: iload_2 // 从局部变量第3个位置的值 压入操作数栈顶
16: ireturn // 返回