12.字节码的初步认识,来自i=i++,i=++i原理分析
首先来代码:
1 2 3 4 5 6 7
| public class TestPlusPlus { public static void main(String[] args) { int i = 0; i++; System.err.println(i); } }
|
然后执行 javap -c TestPlusPlus
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class TestPlusPlus { public TestPlusPlus(); 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_0 //把int型常量0push到栈中,即当前栈顶的值为1 1: istore_1 //pop栈顶的1给变量i。赋值操作(i=0) 2: iinc 1, 1 //自增指令。变量i的值加0,执行完成后,i的值为1 5: getstatic #2 // Field java/lang/System.err:Ljava/io/PrintStream; 8: iload_1 9: invokevirtual #3 // Method java/io/PrintStream.println:(I)V 12: return }
|
然后改造下代码:
1 2 3 4 5 6 7
| public class TestPlusPlus { public static void main(String[] args) { int i = 0; i = i++; System.err.println(i); } }
|
执行 javap -c TestPlusPlus
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class TestPlusPlus { public TestPlusPlus(); 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_0 1: istore_1 2: iload_1 //push局部变量i的值0入栈,即当前栈顶的值为0 3: iinc 1, 1 //自增指令。变量i的值加1,执行完成后,i的值为1 6: istore_1 //pop栈顶的0赋给变量i。即变量i存放的值1被栈顶的元素覆盖,变为0 7: getstatic #2 // Field java/lang/System.err:Ljava/io/PrintStream; 10: iload_1 11: invokevirtual #3 // Method java/io/PrintStream.println:(I)V 14: return }
|
再次改变代码:
1 2 3 4 5 6 7
| public class TestPlusPlus { public static void main(String[] args) { int i = 0; i = ++i; System.err.println(i); } }
|
执行javap -c TestPlusPlus
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class TestPlusPlus { public TestPlusPlus(); 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_0 1: istore_1 2: iinc 1, 1 //自增指令。变量i的值加1,执行完成后,i的值为1 5: iload_1 //push局部变量i的值1入栈,即当前栈顶的值为1 6: istore_1 //pop栈顶的1赋给变量i. 7: getstatic #2 // Field java/lang/System.err:Ljava/io/PrintStream; 10: iload_1 11: invokevirtual #3 // Method java/io/PrintStream.println:(I)V 14: return }
|
主要关注iinc 1, 1和 iload_1和istore_1.