序言
对于操作数栈来说,其实他本身的概念是很模糊的,我们基本上只能通过对字节码指令进行反推才能得出他的结果,但是其实他又深深的藏在字节码指令的每一个角落,基本上所有的字节码指令都是围绕它展开的,小到加减乘除,大到现如今互联网浪潮中的每一次激浪,都离不开他,可以说,他是Java的基石
对于栈这个概念,其实我们多多少少都有所了解,所谓栈,无非就是出栈和入栈,Java虚拟机中的操作数栈也差不多,但是相对我们日常使用或定义的栈来说,操作数栈显然更加严格,也更加复杂,虽然我经常和同学朋友吹比说这玩意看两眼就懂了,但其实真的没那么容易,下面是一段很简单的代码
public class Test {
public static void main(String[] args) {
int i=0,j=0;
i++;
j--;
i-=j;
}
}
基本没什么好讲的,就是简单的加减乘除,我们直接看字节码吧
public static void main(java.lang.String[]);
descriptor:([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=1
0: iconst_0
1: istore_1
2: iconst_0
3: istore_2
4: iinc 1, 1
7: iinc 2, -1
10: iload_1
11: iload_2
12: isub
13: istore_1
14: return
LineNumberTable:
line 3: 0
line 4: 4
line 5: 7
line 6: 10
line 7: 14
line 8: 18
LocalVariableTable:
Start Length Slot Name Signature
0 19 0 args [Ljava/lang/String;
2 17 1 i I
4 15 2 j I
我们按照源代码的行号进行分析操作数栈,第一行
int i=0,j=0;
对应字节码文件
0: iconst_0//将0置于操作数栈顶
1: istore_1//将操作数栈栈顶元素赋值给本地变量2(本地变量从0开始,因此1是第二个),即i
2: iconst_0//将0置于操作数栈顶
3: istore_2//将操作数栈栈顶元素赋值给本地变量3(本地变量从0开始,因此2是第三个),即j
对于操作数栈来说,这就是两次出栈入栈的动作,以下为图示
第二行
i++;
对应字节码文件
4: iinc 1, 1//将i加1,第一个1表示进行操作的变量,见上文,第二个1表示增加的数,这个指令和前面的赋值不同的地方在于它不会导致栈的变化,而是直接对数据进行修改
第三行
j--;
对应字节码文件
5: iinc 2, -1//将j加-1
第四行
i-=j;
对应字节码文件
10: iload_1//i入栈
11: iload_2//j入栈
12: isub//将栈顶两元素相减
13: istore_1//赋值给i
实际上i-=j可以看作两部分
i-j;
i=i-j;
对应的栈操作如下图