package com.bytecode;
public class MyTest7 {
public static void main(String[] args) {
int a = 100;
int b = 200;
a = b + (b = a) * 0;
System.out.println(a);
}
}
输出是:200
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=3, args_size=1
0: bipush 100
2: istore_1
3: sipush 200
6: istore_2
7: iload_2
8: iload_1
9: dup
10: istore_2
11: iconst_0
12: imul
13: iadd
14: istore_1
15: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
18: iload_1
19: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
22: return
LineNumberTable:
line 5: 0
line 6: 3
line 7: 7
line 8: 15
line 9: 22
LocalVariableTable:
Start Length Slot Name Signature
0 23 0 args [Ljava/lang/String;
3 20 1 a I
7 16 2 b I
在这里主要用到的就是 操作数栈和局部变量表 数值之间的来回倒腾。
①从操作数栈 到 局部变量表 是出栈(也叫弹栈)的过程,一般用单词 store 相关的指令。
②从局部变量表 到 操作数栈 是入栈(也叫压栈)的过程 ,意从局部变量表到操作数栈,数值是复制一份过去,并不改变局部变量表里的值,一般用 单词 load 相关的指令。
操作数栈,这个命名其实很贴切,就是为了操作,就是为了操作数的一个后入先出的东西。
字节码分析
stack=3 , 表示 这个栈帧的 操作数栈的深度,最多是3,就像汉诺塔的层数一样,最多是3。刚开始里面是3个空。运算的时候会来回倒腾它。
locals=3,表示 这个栈帧的 局部变量表的局部变量空间是3个Slot ,Slot是局部变量表的最小单元, 一个可以存储32位大小的数据。直白来说就是现在它能存3个变量值到这里面。一般是从索引 1开始取数,不是0没有,而是被关键字“this”占用了
1、初始状态
stack=3, locals=3, args_size=1

2、执行指令 bipush ,作用是将单字节的整数常量值(-128 - 127 )推入操作数栈顶,跟随有一个参数,指明推送的常量值,这里是100,

3、执行指令 istore_1 ,作用是 将操作数栈顶的整型值出栈 并存放到 局部变量表的 索引为1 的Slot 中。如图:

4、执行指令 sipush , 作用和 bipush 差不多,就是 把指定的参数值(这里是200) 入操作数栈,如图:

5、执行指令 istore_2 , 作用和 istore_1 一样 , 就是 把操作数栈栈顶的数值 出栈,并存放到 局部变量表 的索引为2 的Slot 中。如图:

6、接着两条 load 指令,iload_2 , iload_1 这两个的作用是 把Slot2 和 Slot1 的数组复制一份 放入 到操作数栈中。那就变成如图:

OK ,看到了吗,现在 a 和 b 其实都有了两份在内存里,一个在操作数栈里,一个在局部变量表里。好吧,继续看我们的指令,看到最后会是什么结果。
7、执行指令 dup , 这个指令什么意思呢?意思是 “复制栈顶一个或者两个数值并将复制值重新压入栈顶” ,那就是如图。复制不了两个,只能复制一个,深度最大才是3嘛。而且 dup 就是复制一个。

8、执行指令 istore_2 , 这个指令,上面讲过,把 栈顶数据 出栈,存入 Slot2 ,那就是如图:

看,现在 b 的这个位置变成 100了,好像有点意思了,那怎么把 a 变成 200 呢,继续往下看。
9、执行指令 iconst_0 ,这个指令的意思是 取 一个 -1 ~ 5 之间的常量,并压入操作数栈,取谁呢,给的参数是谁,就取谁,取 0 。那就变成这样:

10、执行指令 imul ,这个指令的意思是 乘法指令,是对两个操作数栈上的值进行乘法运算,并把结果重新压入栈中。那就变成这样:(0 * 100 = 0)

11、执行指令 iadd ,这个指令的意思是 加法指令 ,是对两个操作数栈上的值进行 加法运算,并把结果重新压入栈中。那就变成这样:(0 + 200 = 200)

12、执行指令 istore_1 ,这个指令上面讲过了,把栈顶数据出栈,并存放到Slot1中。如图:

网友评论