Java字节码角度分析i++
程序员文章站
2022-03-06 18:35:28
场景:package com.personal.test;import lombok.extern.slf4j.Slf4j;@Slf4j(topic = "LoopIncrementTest")public class LoopIncrementTest { public static void main(String[] args) { int num = 0; for (int i = 0; i < 100; i++) {...
场景:
package com.personal.test;
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "LoopIncrementTest")
public class LoopIncrementTest {
public static void main(String[] args) {
int num = 0;
for (int i = 0; i < 100; i++) {
num = num++;
}
log.debug("LoopIncrementTest result = {}", num);
}
}
以上代码的执行结果为:
[main] DEBUG LoopIncrementTest - LoopIncrementTest result = 0
Process finished with exit code 0
分析:
下面通过一个简单的案例来分析i++操作的原理
package com.personal.test;
import lombok.extern.slf4j.Slf4j;
@Slf4j(topic = "SimpleIncrementTest")
public class SimpleIncrementTest {
public static void main(String[] args) {
int num = 0;
num = num++;
log.debug("SimpleIncrementTest result = {}", num);
}
}
通过将num = num++的操作分离来分析代码的执行过程,以上代码通过javap指令编译成字节码的结果为:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=2, args_size=1
0: iconst_0
1: istore_1
2: iload_1
3: iinc 1, 1
6: istore_1
7: getstatic #2 // Field log:Lorg/slf4j/Logger;
10: ldc #3 // String SimpleIncrementTest result = {}
12: iload_1
13: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
16: invokeinterface #5, 3 // InterfaceMethod org/slf4j/Logger.debug:(Ljava/lang/String;Ljava/lang/Object;)V
21: return
通过查阅Oracle官方文档,字节码中的0、1、2、3、6这几步操作的官方解释分别为:
Code | Description |
---|---|
iconst_<i> |
Push the int constant
(-1, 0, 1, 2, 3, 4 or 5) onto the operand stack.
|
istore_<n> |
The must be an index into the local variable array of the current frame (§2.6). The value on the top of the operand stack must be of type int. It is popped from the operand stack, and the value of the local variable at is set to value.
|
iload_<n> |
The must be an index into the local variable array of the current frame (§2.6). The local variable at must contain an int. The value of the local variable at is pushed onto the operand stack.
|
iinc |
The index is an unsigned byte that must be an index into the local variable array of the current frame (§2.6). The const is an immediate signed byte. The local variable at index must contain an int. The value const is first sign-extended to an int, and then the local variable at index is incremented by that amount.
|
下面通过图示来展示以上字节码的执行过程
1.iconst_0
2.istore_1
3.iload_1
4.iinc 1, 1
5.istore_1
通过分析字节码的执行过程,关键在第四步iinc操作,iinc的自增是改变了本地变量表的值,而不会对操作数栈中的数据有任何影响。因此,在本地变量表中的变量完成自增后,又将之前存储在操作数栈中的常量0弹栈赋值给了本地变量表中的变量导致num的值由1变成了0。
本文地址:https://blog.csdn.net/weixin_44540161/article/details/111866432