learn and grow up

通过字节码简单解析i++和++i的区别

字数统计: 343阅读时长: 1 min
2020/07/26 Share

写在前面

最近闲暇时间在研究jvm虚拟机原理,所以把日常看到的、学习到的记录下来,这篇文章比较简单,主要是基于上篇文章简单了解下i++和++i的区别

实例

直接上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//source
public int iinc(){
return a++;
}
public int inci(){
return ++a;
}

//class
public int iinc();
descriptor: ()I
flags: ACC_PUBLIC
Code:
stack=4, locals=1, args_size=1
0: aload_0
1: dup
2: getfield #8 // Field a:I
5: dup_x1
6: iconst_1
7: iadd
8: putfield #8 // Field a:I
11: ireturn
LineNumberTable:
line 32: 0
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 this Ljavp/JapTest;

public int inci();
descriptor: ()I
flags: ACC_PUBLIC
Code:
stack=3, locals=1, args_size=1
0: aload_0
1: dup
2: getfield #8 // Field a:I
5: iconst_1
6: iadd
7: dup_x1
8: putfield #8 // Field a:I
11: ireturn
LineNumberTable:
line 35: 0
LocalVariableTable:
Start Length Slot Name Signature
0 12 0 this Ljavp/JapTest;

​ 仔细对比可以发现,两个方法的5、6、7三行指令发生了顺序上的变化。所以i++是先拷贝一份i的值,然后对栈顶的i的副本进行加一,随后将副本i弹出,返回i。++i则是先对i进行加1,然后再拷贝,再弹出,再返回。

​ 其他:根据上面这些指令也可以发现多线程操作中这两个方法不安全的地方,不同线程在不同栈对同一对象执行操作,getfield和putfield都可能会覆盖对方。所以需要加锁。

CATALOG
  1. 1. 写在前面
  2. 2. 实例