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

张春  金牌会员 | 2024-6-22 13:01:52 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 683|帖子 683|积分 2049

JVM为什么要选用基于栈的指令集架构



  • 与基于寄存器的指令集架构相比,基于栈的指令集架构不依赖于硬件,因此可移植性更好,跨平台性更好
  • 因为栈结构的特性,永久都是先处理栈顶的第一条指令,因此大部分指令都是零地址指令,以是指令集更小
  • 固然指令集更小,但是同样的一步操作,比基于寄存器所需的指令更多,性能也相对慢

++i的指令集



  • 如下文所示,界说了一段简洁的代码:
  1. public class Demo01 {
  2.     private void test1(){
  3.         int i = 10;
  4.         i = ++i;
  5.     }
  6. }
复制代码


  • 根据加号在前就等于“先加加再带入盘算”的常识,i的结果必然是11
  • 如今再从指令来看到底是履历了什么样的操作才变成了11:
反编译结果如图所示:


内容和表明如下:

  1. 0 bipush 10   --将10压入操作数栈
  2. 2 istore_1    --将栈顶数字10存入局部变量表索引为1的位置(索引为0的位置放的是this)
  3. 3 iinc 1 by 1 -- *** 将局部变量表中索引为1的位置的数(也就是10)直接加1 ***
  4. 6 iload_1     -- *** 将局部变量表中索引为1的位置的数(现在是11)压入操作数栈 ***
  5. 7 istore_1    -- *** 将栈顶数字11存入局部变量表索引为1的位置 ***
  6. 8 return      --返回11
复制代码

同时对比一下i++的指令集



  • 如下文所示,界说了一段简洁的代码:
  1. public class Demo01 {
  2.     private void test1(){
  3.         int i = 10;
  4.         i = i++;
  5.     }
  6. }
复制代码


  • 根据加号在后就等于“先带入盘算再加加”的常识,i的结果必然是10
  • 如今再从指令来看到底是履历了什么样的操作才变成了10:
反编译结果如图所示:


内容和表明如下:

  1. 0 bipush 10   --将10压入操作数栈
  2. 2 istore_1    --将栈顶数字10存入局部变量表索引为1的位置(索引为0的位置放的是this)
  3. 3 iload_1     -- *** 将局部变量表中索引为1的位置的数(现在是10)压入操作数栈 ***
  4. 4 iinc 1 by 1 -- *** 将局部变量表中索引为1的位置的数(也就是10)直接加1 ***
  5. 7 istore_1    -- *** 将栈顶数字10存入局部变量表索引为1的位置 ***
  6. 8 return      --返回10
复制代码

两种环境的不同之处:



  • 最重要的区别就是图片的红框处以及表明中的星号标注处,i++的时间,读入操作数栈的是没有进行加1的值,而++i的时间,读入操作数栈的是加过1的值
  • ++i的时间是先把局部变量表中的10加成了11,然后把11读取到操作数栈,然后再覆盖回局部变量表,以是最后返回了11
  • i++的时间是把10读取到了操作数栈,然后把局部变量表中的10加成了11,但是下一步又用操作数栈的10 覆盖了局部变量表中的11,以是最后返回了10

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张春

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表