张春 发表于 2024-6-22 13:01:52

【JVM】从编译后的指令集来再次明白++i和i++的实行次序

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 【JVM】从编译后的指令集来再次明白++i和i++的实行次序