Java的i = i++与i=++i的去呗从JVM指令讲解图文并茂,一文必懂

一、Java的i = i++深入JVM指令讲解 图文并茂 看了必懂

先看一段简单的代码

package com.zhou.jvm.runtimedataAreainstructionset;

/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/5-19:55
 */
public class TestPlusPlus {
    public static void main(String[] args) {
        int i = 8;
        i = i++;
        System.out.println(i);
    }
}

最后程序打印的结果是8不是9

Java的i = i++与i=++i的去呗从JVM指令讲解图文并茂,一文必懂_第1张图片

那么这个是为什么呢?我们从JVM指令来看

编译这个类之后我们用jclasslib插件show bytecode with jclasslib,可以看到如下

Java的i = i++与i=++i的去呗从JVM指令讲解图文并茂,一文必懂_第2张图片

我把里面的Bytecode单独拿出来,粘在这里

 0 bipush 8
 2 istore_1
 3 iload_1
 4 iinc 1 by 1
 7 istore_1
 8 getstatic #2 
11 iload_1
12 invokevirtual #3 
15 return

接下来一条一条指令的解析

1. bipush 8

第一步,bipush指令具体的含义就是把一个int类型的数据压入操作数栈。具体的可以参照官网链接,如下图所示把8压入了操作数栈

Java的i = i++与i=++i的去呗从JVM指令讲解图文并茂,一文必懂_第3张图片

2. istore_1

第二步,istore_1就是将操作数栈的数字弹出栈并写入局部变量表当中建立的一个index值为1的索引的变量,这里程序的i变量此时就为8,完成了int i = 8的操作。

Java的i = i++与i=++i的去呗从JVM指令讲解图文并茂,一文必懂_第4张图片

3. iload_1

第三步,iload_1指令就是将局部变量表中的值再次压入操作数栈当中去。所以此时操作数栈里面的值此时为8

Java的i = i++与i=++i的去呗从JVM指令讲解图文并茂,一文必懂_第5张图片

4. iinc 1 by 1

第四步,iinc 1 by 1就是将局部变量表中索引值为1的变量加一,就是完成了i++这一步操作,此时局部变量表中的i为9

Java的i = i++与i=++i的去呗从JVM指令讲解图文并茂,一文必懂_第6张图片

5. istore_1

第五步,istore_1就是将操作数栈的数字弹出栈并写入局部变量表当中建立的一个index值为1的索引的变量,这里程序的i变量此时就为8,完成了int i = i++的操作。

Java的i = i++与i=++i的去呗从JVM指令讲解图文并茂,一文必懂_第7张图片

6. iload_1

Java的i = i++与i=++i的去呗从JVM指令讲解图文并茂,一文必懂_第8张图片

因此最后输出的就是8

二、换成i=++i的JVM指令研究

package com.zhou.jvm.runtimedataAreainstructionset;

/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/5-19:55
 */
public class TestPlusPlus {
    public static void main(String[] args) {
        int i = 8;
        i = ++i;
        System.out.println(i);
    }
}

Java的i = i++与i=++i的去呗从JVM指令讲解图文并茂,一文必懂_第9张图片

这个类的Bytecode

Java的i = i++与i=++i的去呗从JVM指令讲解图文并茂,一文必懂_第10张图片

i=++i的bytecode

 0 bipush 8
 2 istore_1
 3 iinc 1 by 1
 6 iload_1
 7 istore_1
 8 getstatic #2 
11 iload_1
12 invokevirtual #3 
15 return

把i = i++的bytecode拿出来对比

 0 bipush 8
 2 istore_1
 3 iload_1
 4 iinc 1 by 1
 7 istore_1
 8 getstatic #2 
11 iload_1
12 invokevirtual #3 
15 return

可以看出两者之间的区别在于 iload_1 和 iinc 1 by 1的顺序问题

i=++i的是先 iinc 1 by 1再 iload_1,就是说先对局部变量表的变量进行自增再把这个自增以后的值压入操作数栈,自然这个操作数栈的数据已经+1了

i=i++的是先iload_1 再iinc 1 by 1,就是说先把局部变量表中的变量的值压入操作数栈,再进行自增操作,所以这个对于后续的istore_1操作有影响,使得这个最终的局部变量表中的数据还是之前没有加1的那个数值。

你可能感兴趣的:(JVM,java,jvm,栈,局部变量表,操作数栈)