Java字节码角度分析i++

场景:

package com.personal.test;

import lombok.extern.slf4j.Slf4j;

@Slf4j(topic = "LoopIncrementTest")
public class LoopIncrementTest {

    public static void main(String[] args) {
        int num = 0;
        for (int i = 0; i < 100; i++) {
            num = num++;
        }
        log.debug("LoopIncrementTest result = {}", num);
    }

}

以上代码的执行结果为:

[main] DEBUG LoopIncrementTest - LoopIncrementTest result = 0

Process finished with exit code 0

分析:

下面通过一个简单的案例来分析i++操作的原理

package com.personal.test;

import lombok.extern.slf4j.Slf4j;

@Slf4j(topic = "SimpleIncrementTest")
public class SimpleIncrementTest {

    public static void main(String[] args) {
        int num = 0;
        num = num++;
        log.debug("SimpleIncrementTest result = {}", num);
    }

}

通过将num = num++的操作分离来分析代码的执行过程,以上代码通过javap指令编译成字节码的结果为:

 public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=2, args_size=1
         0: iconst_0
         1: istore_1
         2: iload_1
         3: iinc          1, 1
         6: istore_1
         7: getstatic     #2                  // Field log:Lorg/slf4j/Logger;
        10: ldc           #3                  // String SimpleIncrementTest result = {}
        12: iload_1
        13: invokestatic  #4                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        16: invokeinterface #5,  3            // InterfaceMethod org/slf4j/Logger.debug:(Ljava/lang/String;Ljava/lang/Object;)V
        21: return

通过查阅Oracle官方文档,字节码中的0、1、2、3、6这几步操作的官方解释分别为:

CodeDescription
iconst_<i>
Push the int constant (-1, 0, 1, 2, 3, 4 or 5) onto the operand stack.
istore_<n>
The must be an index into the local variable array of the current frame (§2.6). The value on the top of the operand stack must be of type int. It is popped from the operand stack, and the value of the local variable at is set to value.
iload_<n>
The must be an index into the local variable array of the current frame (§2.6). The local variable at must contain an int. The value of the local variable at is pushed onto the operand stack.
iinc
The index is an unsigned byte that must be an index into the local variable array of the current frame (§2.6). The const is an immediate signed byte. The local variable at index must contain an int. The value const is first sign-extended to an int, and then the local variable at index is incremented by that amount.

下面通过图示来展示以上字节码的执行过程
1.iconst_0
在这里插入图片描述

2.istore_1
在这里插入图片描述
3.iload_1

在这里插入图片描述
4.iinc 1, 1

在这里插入图片描述
5.istore_1
在这里插入图片描述
通过分析字节码的执行过程,关键在第四步iinc操作,iinc的自增是改变了本地变量表的值,而不会对操作数栈中的数据有任何影响。因此,在本地变量表中的变量完成自增后,又将之前存储在操作数栈中的常量0弹栈赋值给了本地变量表中的变量导致num的值由1变成了0。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值