jvm自增,自减运行原理

在jvm中,涉及到变量运算时,会发生压栈弹栈等动作,但如果仅仅是自增和自减,那么jvm会直接在本地变量中实现。

public class JavaTest{

    public static void main(String[] args){
        int a=1,b=1,c=1,d=1;
        a++;
        ++b;
        c = c++;
        d=++d;
        System.out.println(a+"..."+b+"..."+c+"..."+d);
    }
}

这段代码很简单,运行结果为2,2,1,2。
对于这样的结果大家可能都觉得是对的,因为c=c++的时候会先执行赋值操作,再进行自增,所以c等于1。但是c进行赋值之后,自增的操作也是c本身,为什么c这个变量不等于自增后的数值呢?
我们使用javap来将这段代码进行解析,结果如下:

F:\>javap -c JavaTest
Compiled from "JavaTest.java"
public class JavaTest {
  public JavaTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_1
       3: istore_2
       4: iconst_1
       5: istore_3
       6: iconst_1
       7: istore        4
       9: iinc          1, 1
      12: iinc          2, 1
      15: iload_3
      16: iinc          3, 1
      19: istore_3
      20: iinc          4, 1
      23: iload         4
      25: istore        4
      27: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      30: new           #3                  // class java/lang/StringBuilder
      33: dup
      34: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      37: iload_1
      38: invokevirtual #5                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      41: ldc           #6                  // String ...
      43: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      46: iload_2
      47: invokevirtual #5                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      50: ldc           #6                  // String ...
      52: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      55: iload_3
      56: invokevirtual #5                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      59: ldc           #6                  // String ...
      61: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      64: iload         4
      66: invokevirtual #5                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      69: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      72: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      75: return
}

下面我们来分析一下,前面0-7可以看出是定义了4个变量,分别进行压栈和弹栈操作,将变量最终放入到本地变量中。9这个操作就对应于代码中的a++,可以看出没有进行压栈和弹栈,只是执行了iinc,也就是自增操作,所以这个时候,本地变量中a就等于2。12对应于代码中的++b,情况和9类似。c=c++对应于15-19,从这里可以看出,jvm先执行了压栈,将c压入栈顶,然后执行自增操作,所以这个时候,栈顶的c为1,本地变量c为2,但是在这个时候,19又将栈顶的c弹栈并赋值给本地变量c了,所以本地变量c最终为1。d=++d和上面原理是一致的。
通过对代码的汇编码的分析,我们可以知道c=c++为什么等于自增前的c了,其实不是因为先进行了赋值,自增后的数据没有再次赋值,而是由于自增后被原数据给覆盖了。

上一篇:java随机流


下一篇:db block gets ,consistent reads