Java i++操作不是原子性的,怎么理解?

Java中的i++操作分为三步:

  1. 将i压入栈顶
  2. 将1压入栈顶
  3. 将+号压入栈顶,发现是运算符,弹出i和1,进行加法运算,再返回栈顶。

通过Java的字节码指令来验证

编写下面这段java程序:

class Main{
	int i; 
	public static void main(String[] args){
		new Main().increas();
	}
	public void increas(){
		i++;
	}
}

运行javac命令,进行编译:

javac Main.java

得到Main.class字节码文件,此时如果直接打开class文件,是一串二进制数据,无法阅读,可以通过javap命令反编译class文件:

javap Main.class

得到以下输出:

Compiled from "Main.java"
class Main {
  int i;

  Main();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class Main
       3: dup
       4: invokespecial #3                  // Method "<init>":()V
       7: invokevirtual #4                  // Method increas:()V
      10: return

  public void increas();
    Code:
       0: aload_0
       1: dup
       2: getfield      #5                  // Field i:I
       5: iconst_1
       6: iadd
       7: putfield      #5                  // Field i:I
      10: return
}

我们主要看increas方法部分:

  public void increas();
    Code:
       0: aload_0
       1: dup
       2: getfield      #5                  // Field i:I
       5: iconst_1
       6: iadd
       7: putfield      #5                  // Field i:I

以下是对应字节码指令的解释:

在Java中,每个操作都对应一个或多个字节码指令。这些指令是Java虚拟机(JVM)执行的最低层次的命令。

  1. aload_0:

    • 这条指令用于将局部变量数组中的第一个元素(在这种情况下是this引用,指向当前的Main对象)加载到操作栈上。在非静态方法中,局部变量的第0位总是用于存储对当前对象的引用。
  2. dup:

    • dup是一个复制指令,它复制操作栈顶的值并将复制值压回栈顶。这里它用来复制this引用,因此操作栈上会连续有两份this引用。
  3. getfield #5:

    • getfield指令用于获取对象的实例字段。这里它使用#5作为索引,这通常指向常量池中的一个字段描述,表示Main类中的i字段(类型为int)。指令执行后,它会将this.i的值加载到栈顶,替换掉之前的一个this引用。
  4. iconst_1:

    • 这条指令将整数1压入操作栈顶。这用于后续的增加操作。
  5. iadd:

    • iadd是一个整数加法指令,它从栈顶弹出两个整数值,将它们相加,然后将结果压回栈顶。在这里,它将栈顶的1(通过iconst_1加载)和Main.i的当前值(通过getfield加载)相加。
  6. putfield #5:

    • putfield指令用于将栈顶的值(这里是i + 1的结果)赋值给对象的实例字段。与getfield一样,#5指代Main类中的i字段。在这里,它首先弹出栈顶的增加后的值(i+1),然后弹出下一个栈顶的this引用,最终将增加后的值赋给这个引用指向的对象的i字段。

通过上述指令,increas方法实现了i字段的自增操作。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值