字节码角度分析++i和i++

25 篇文章 0 订阅

通过示例从字节码的角度研究++i和i++底层发生的事情。参考《jvm字节码从入门到精通》

i++字节码分析

package com.java.bt;

public class BTTest {
    public static void test() {
        int i = 0;
        for (int j = 0 ; j < 50; j++) {
            i = i++;
        }
        System.out.println(i);
    }

    public static void main(String[] args) {
        test();
    }
}

此段代码运行之后输出0。

通过javap -v BTTest命令对.java文件,反编译获得字节码。
在这里插入图片描述
分析:

  • 其中0~1行对应int i = 0;
    iconst_0把0压入操作数栈。
    istore_0将栈顶元素存入局部变量表(LocalVariableTable)0槽(slot)中。
  • 其中2~3行对应int j = 0;同理。
  • 第4~7对应j < 50;判断是否跳出循环。
    iload_1将局部变量表槽1中的元素放入栈顶。
    bipush 50将50压入栈顶。
    if_icmpge 21 将栈顶两个元素取出进行比较,如果 j >= 50 则跳转到第21行。
  • 第7~14行对应i = i++
    iload_0将i读取到栈顶。
    iinc 0, 1 iinc 0, 1指令可以直接让局部变量表槽0位置的数+1,而不用先把数字放到操作数栈中。
    istore_0此时将栈顶的元素存入槽0中(覆盖了增加1以后的i)。
  • 第15行对应j++
    iinc 1, 1直接让槽1中的变量(j)增加1。
  • goto 4跳转到第四行,for循环体结束。
  • 21-25行对应System.out.println(i)
    getstatic #2读入静态变量System.out(变量名存在s常量池#2位置)
    iload_0将i压入栈中。
    invokespecialvirtual #3调用栈顶对象的println方法。

++i字节码分析

将上述代码稍作修改,如下:

package com.java.bt;

public class BTTest {
    public static void test() {
        int i = 0;
        for (int j = 0 ; j < 50; j++) {
            i = ++i;
        }
        System.out.println(i);
    }

    public static void main(String[] args) {
        test();
    }
}

运行结果为:50

重新编译再查看其字节码如下:
在这里插入图片描述
分析:
该字节码唯一的差别在10~14行。

  1. ++i先执行iinc 0, 1将槽0的变量i增加1;
  2. 再通过iload_0将其取出;
  3. 通过istore_0将其赋值给i。

因此每一轮循环i都加1,最终结果为50。

i = i++ + ++i

示例代码如下:

package com.java.bt;

public class BTTest {
    public static void main(String[] args) {
        int i = 0;
        i = i++ + ++i;
        System.out.println(i);
    }
}

此段代码似乎没什么意义,但是通过分析其字节码可以得到输出的结果,字节码如下:
在这里插入图片描述
分析:

  • 第0~1行中istore_1表示将0存入槽1中。(因为槽0中存的是main方法的参数)
  • 第2-11行是主要关注的,通过字节码可以清楚的分析得到最终槽1中的变量(i)值为2。

除此之外还可以通过字节码分析i = ++i + ++i以及i = i++ + i++等表达式的结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值