源码:
package cn.itcast.jvm.t3.bytecode;
/**
* 从字节码角度分析 a++ 相关题目
*/
public class Demo3_2 {
public static void main(String[] args) {
int a = 10;
int b = a++ + ++a + a--;
System.out.println(a);
System.out.println(b);
}
}
字节码:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=1
0: bipush 10
2: istore_1
3: iload_1
4: iinc 1, 1
7: iinc 1, 1
10: iload_1
11: iadd
12: iload_1
13: iinc 1, -1
16: iadd
17: istore_2
21: iload_1
22: invokevirtual #3 // Method
java/io/PrintStream.println:(I)V
25: getstatic #2 // Field
java/lang/System.out:Ljava/io/PrintStream;
28: iload_2
29: invokevirtual #3 // Method
java/io/PrintStream.println:(I)V
32: return
LineNumberTable:
line 8: 0
line 9: 3
line 10: 18
line 11: 25
line 12: 32
LocalVariableTable:
Start Length Slot Name Signature
0 33 0 args [Ljava/lang/String;
3 30 1 a I
18 15 2 b I
分析:
- 注意 iinc 指令是直接在局部变量 slot 上进行运算
- a++ 和 ++a 的区别是先执行 iload 还是 先执行 iinc
- 执行bipush指令 将a push到操作数栈中

- 执行istore_1 指令将 10放到局部变量表中的第一个槽位

- 执行iload_1指令,将局部变量表中的1号槽位的值压入操作数栈

- 执行iinc 1,1指令,第一个1是指局部变量表的第1号槽位,第二个1是指加1(iinc指令是直接在局部变量表中进行操作,不会压入到操作数栈)

- ++a,先执行iinc

- 在执行iload_1指令,将操作后的12压入操作数栈

- 再执行iadd指令,将操作数栈的值进行相加

- 执行iload_1指令将12再次压入操作数栈

- 执行iinc指令,将局部变量表中的12-1

- 执行iadd指令将操作数栈的12与22进行相加

- 最后执行istore_2将操作数栈中的值弹出栈,存放到局部变量表中的第二个槽位,至此完成了b变量的赋值。

最终的结果为:
a=11,b=34
本文深入分析了Java字节码指令如何处理a++运算符,详细解释了iinc与iload指令的交互作用,揭示了a++和++a在字节码层面的区别,以及如何影响最终结果。
803






