JVM为什么要选用基于栈的指令集架构
- 与基于寄存器的指令集架构相比,基于栈的指令集架构不依赖于硬件,因此可移植性更好,跨平台性更好
- 因为栈结构的特性,永远都是先处理栈顶的第一条指令,因此大部分指令都是零地址指令,所以指令集更小
- 虽然指令集更小,但是同样的一步操作,比基于寄存器所需的指令更多,性能也相对慢
++i的指令集
public class Demo01 {
private void test1(){
int i = 10;
i = ++i;
}
}
- 根据加号在前就等于“先加加再带入计算”的常识,i的结果必然是11
- 现在再从指令来看到底是经历了什么样的操作才变成了11:
反编译结果如图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/e570eb8abb934452ac655b9d04f29a50.png)
内容和解释如下:
0 bipush 10 --将10压入操作数栈
2 istore_1 --将栈顶数字10存入局部变量表索引为1的位置(索引为0的位置放的是this)
3 iinc 1 by 1 -- *** 将局部变量表中索引为1的位置的数(也就是10)直接加1 ***
6 iload_1 -- *** 将局部变量表中索引为1的位置的数(现在是11)压入操作数栈 ***
7 istore_1 -- *** 将栈顶数字11存入局部变量表索引为1的位置 ***
8 return --返回11
同时对比一下i++的指令集
public class Demo01 {
private void test1(){
int i = 10;
i = i++;
}
}
- 根据加号在后就等于“先带入计算再加加”的常识,i的结果必然是10
- 现在再从指令来看到底是经历了什么样的操作才变成了10:
反编译结果如图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/760bff1559544406bb5fa46b0d827a80.png)
内容和解释如下:
0 bipush 10 --将10压入操作数栈
2 istore_1 --将栈顶数字10存入局部变量表索引为1的位置(索引为0的位置放的是this)
3 iload_1 -- *** 将局部变量表中索引为1的位置的数(现在是10)压入操作数栈 ***
4 iinc 1 by 1 -- *** 将局部变量表中索引为1的位置的数(也就是10)直接加1 ***
7 istore_1 -- *** 将栈顶数字10存入局部变量表索引为1的位置 ***
8 return --返回10
两种情况的不同之处:
- 最主要的区别就是图片的
红框
处以及解释中的星号标注
处,i++的时候,读入操作数栈
的是没有进行加1的值,而++i的时候,读入操作数栈
的是加过1的值
++i
的时候是先把局部变量表
中的10
加成了11
,然后把11
读取到操作数栈
,然后再覆盖回局部变量表
,所以最后返回了11
i++
的时候是把10
读取到了操作数栈
,然后把局部变量表
中的10
加成了11
,但是下一步又用操作数栈的10
覆盖了局部变量表中的11
,所以最后返回了10