JVMJVM05(从字节码角度分析i++和++i的执行流程)
Posted 温文艾尔
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVMJVM05(从字节码角度分析i++和++i的执行流程)相关的知识,希望对你有一定的参考价值。
⭐️写在前面
这里是温文艾尔の学习之路
- 👍如果对你有帮助,给博主一个免费的点赞以示鼓励把QAQ
- 👋博客主页🎉 温文艾尔の学习小屋
- ⭐️更多文章👨🎓请关注温文艾尔主页📝
- 🍅文章发布日期:2022.02.06
- 👋java学习之路!
- 欢迎各位🔎点赞👍评论收藏⭐️
- 🎄新年快乐朋友们🎄
- 👋jvm学习之路!
- ⭐️上一篇内容:JVM04(类加载与字节码-图解方法执行流程)
文章目录
1.i++
原始代码
public class Demo03
public static void main(String[] args)
int a = 10;
int b = a++ + ++a + a--;
System.out.println(a);
System.out.println(b);
javap反编译后的.class字节码文件
Classfile /F:/2021年12月之后的Idea项目/jvmProject/out/production/jvmProj
ect/com/wql/jvm/ClassInfo/Demo03.class
Last modified 2022年1月22日; size 599 bytes
SHA-256 checksum 2fb1f080d8858a312c0f3c65356a84fea66a987ae74607ef26ac5
aa49fbedfee
Compiled from "Demo03.java"
public class com.wql.jvm.ClassInfo.Demo03
minor version: 0
major version: 52
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #4 // com/wql/jvm/ClassInfo/Demo0
3
super_class: #5 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
#1 = Methodref #5.#22 // java/lang/Object."<init>":(
)V
#2 = Fieldref #23.#24 // java/lang/System.out:Ljava/
io/PrintStream;
#3 = Methodref #25.#26 // java/io/PrintStream.println
:(I)V
#4 = Class #27 // com/wql/jvm/ClassInfo/Demo0
3
#5 = Class #28 // java/lang/Object
#6 = Utf8 <init>
#7 = Utf8 ()V
#8 = Utf8 Code
#9 = Utf8 LineNumberTable
#10 = Utf8 LocalVariableTable
#11 = Utf8 this
#12 = Utf8 Lcom/wql/jvm/ClassInfo/Demo03;
#13 = Utf8 main
#14 = Utf8 ([Ljava/lang/String;)V
#15 = Utf8 args
#16 = Utf8 [Ljava/lang/String;
#17 = Utf8 a
#18 = Utf8 I
#19 = Utf8 b
#20 = Utf8 SourceFile
#21 = Utf8 Demo03.java
#22 = NameAndType #6:#7 // "<init>":()V
#23 = Class #29 // java/lang/System
#24 = NameAndType #30:#31 // out:Ljava/io/PrintStream;
#25 = Class #32 // java/io/PrintStream
#26 = NameAndType #33:#34 // println:(I)V
#27 = Utf8 com/wql/jvm/ClassInfo/Demo03
#28 = Utf8 java/lang/Object
#29 = Utf8 java/lang/System
#30 = Utf8 out
#31 = Utf8 Ljava/io/PrintStream;
#32 = Utf8 java/io/PrintStream
#33 = Utf8 println
#34 = Utf8 (I)V
public com.wql.jvm.ClassInfo.Demo03();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object
."<init>":()V
4: return
LineNumberTable:
line 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/wql/jvm/ClassInfo/Demo03;
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
18: getstatic #2 // Field java/lang/System.
out:Ljava/io/PrintStream;
21: iload_1
22: invokevirtual #3 // Method java/io/PrintStr
eam.println:(I)V
25: getstatic #2 // Field java/lang/System.
out:Ljava/io/PrintStream;
28: iload_2
29: invokevirtual #3 // Method java/io/PrintStr
eam.println:(I)V
32: return
LineNumberTable:
line 11: 0
line 12: 3
line 13: 18
line 14: 25
line 15: 32
LocalVariableTable:
Start Length Slot Name Signature
0 33 0 args [Ljava/lang/String;
3 30 1 a I
18 15 2 b I
SourceFile: "Demo03.java"
本次我们主要分析这部分的操作
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
分析:
- 注意iinc指令是直接在局部变量slot上进行运算
- a++和++a的区别是先执行iload还是先执行iinc
执行流程
1.bipush 10
含义:将10放入操作数栈中
2.istore_1
含义:弹出栈顶元素,放入局部变量槽的1号位置,对应a=10操作
然后开始执行a++的操作,a++顺序为先iload再自增
3.iload_1
将局部变量a=10压入操作栈栈顶
4.iinc 1 1
第一个参数是对哪个槽位做自增,第二个参数是自增多少
例如iinc 1 1意思是是局部变量表的1号槽位中的变量+1
下面开始++i的操作,顺序是先自增再iload
5.iinc 1 1
局部变量表的1号槽位中的变量+1,此时i=12
6.iload_1
将局部变量12压入操作数栈
7.iadd
弹出操作数栈栈顶的两个数字进行相加10+12 = 22,并将结果压入操作数栈
下面进行i–的操作
8.iload_1
将局部变量表1号槽位的变量压入栈顶
9.iinc 1 -1
对局部变量表1号槽位的变量进行-1操作
10.iadd
弹出栈顶的两个元素进行相加
istore 2
将栈顶元素弹出到局部变量表的2号槽位
故b=34,a=11
方法执行结束
以上是关于JVMJVM05(从字节码角度分析i++和++i的执行流程)的主要内容,如果未能解决你的问题,请参考以下文章