关于i = i++的浅析

有这样一段Java代码:

int i = 0;
i = i++;
System.out.println(i);


打印出i的值是多少? 这个问题不止一次跟人讨论过,分析它还是要从JVM的结构以及指令入手。

JVM的内存空间有一部分是栈,每个线程有自己的栈,栈由栈帧组成,每个Java方法调用会向栈中压入一个栈帧,方法执行完成后会弹出该栈帧。
栈帧又分为局部变量区和操作数栈两部分,局部变量区存放方法调用时的参数,方法内定义的局部变量,等等;操作数栈是进行运算的地方,同时存放计算的中间结果,方法的返回值,等等。

Java中的一条赋值语句是由两条JVM指令完成的,第一条指令将“=”右边的值压入操作数栈,第二条指令将操作数栈顶的值弹出,赋给“=”左边的变量。

上面的代码编译成class文件后,关键的字节码序列如下:

0  iconst_0
1 istore_1 [i]
2 iload_1 [i]
3 iinc 1 1 [i]
6 istore_1 [i]


解释如下:
iconst_0,将int值0压入操作数栈
istore_1,将栈顶的0弹出,赋给局部变量区1号索引的局部变量i
至此完成int i = 0

iload_1,将局部变量区1号索引的变量i值0压入操作数栈
iinc 1 1,将局部变量区1号索引的值加1,操作数栈不发生变化
istore_1,将栈顶的0弹出,赋给局部变量区1号索引的i
至此完成i = i++,所以最后i的值为0

这里关键的地方有两点:
1、iinc 指令是直接对局部变量区进行操作,操作数栈不发生任何变化,这是由JVM规范定义的。
2、i++是先赋值,再自增,所以iload指令在iinc之前。 SUN的Hotspot VM编译后将iinc指令插到了赋值的iload和istore指令之间。 其他的VM实现编译可能会产生不同的结果,可能将iinc放到iload和istore后面(这点未证实,是个人的猜想)

现实中这种代码不会有人写,纯拿来分析问题罢了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值