javabytecode

Difference in implementation of x = x + 1 and x++


My professor recently said that although x = x + 1 and x++ will obviously give the same result, there is a difference in how they are implemented in the JVM. What does it mean? Isn't compiler like: hey, I see x++ so I will switch it to x = x + 1 and carry on?

I doubt there is any difference when it comes to efficiency, but I would be surprised if assembly would be different in those cases...


Solution

  • My professor recently said that although x = x + 1 and x++ will obviously give the same result

    I guess your professor perhaps meant - the value of x after x = x + 1 and x++ will be same. Just to re-phrase, as it seems to be creating confusion in interpreting the question.

    Well, although the value of x will be same, they are different operators, and use different JVM instructions in bytecode. x + 1 uses iadd instruction, whereas x++ uses iinc instruction. Although this is compiler dependent. A compiler is free to use a different set of instructions for a particular operation. I've checked this against javac compiler.

    For eclipse compiler, from one of the comment below from @Holger:

    I just tested it with my eclipse and it produced iinc for both expressions. So I found one compiler producing the same instructions

    You can check the byte code using javap command. Let's consider the following class:

    class Demo {
        public static void main(String[] args) {
            int x = 5;
    
            x = x + 1;
            System.out.println(x);
    
            x++;
            System.out.println(x);
        }
    } 
    

    Compile the above source file, and run the following command:

    javap -c Demo
    

    The code will be compiled to the following bytecode (just showing the main method):

     public static void main(java.lang.String[]);
       Code:
          0: iconst_5
          1: istore_1
          2: iload_1
          3: iconst_1
          4: iadd
          5: istore_1
          6: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
          9: iload_1
         10: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
         13: iinc          1, 1
         16: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         19: iload_1
         20: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
         23: return