本文主要讲load,store,const,push等字节码的实例即应用。
声明局部变量并赋值
源程序
int x = 2;
int y = 3;
字节码
0 iconst_2 将常量(2)压入操作数栈中
1 istore_1 将操作栈的值弹出,即常量(2)并赋值给第1个局部变量x
2 iconst_3 将常量(3)压入操作数栈中
3 istore_2 弹出当前操作数栈中的第一个值,即(3),并赋值给第二个局部变量,即y
4 return
先声明局部变量,再赋值
程序
int i, j;
j = 200;
i = 100;
字节码
0 sipush 200 将Short型数字常量(200)加载到操作数栈中
3 istore_2 弹出当前操作数栈中的第一个值(200),并赋值给第二个局部变量(j)
4 bipush 100 将Byte型常量(100)加载到操作数栈中
6 istore_1 弹出当前操作数栈中的第一个值(100), 并赋值给第一个局部变量(i)
7 return
分析
(1)对于局部变量的声明顺序将会导致存在局部变量表中的顺序
(2)对于一步的赋值操作,会先把常量加载到操作数栈中并赋值
(3)istore_<i>
,i即表示局部变量的下标,从0开始,因为实例程序是main方法,所以args是下标为0的局部变量
(4)先声明后赋值,对于常量如100,1这种数字,会根据实际的常量的值来进行设置值的类型,二如果是直接int x = 1 ,那么1的存储方式就是一个Integer
(5)bipush/sipush这种push方式,会直接获取它的直接操作数,即后面的100,并压入操作数栈中
Tip: 当int取值-1~5采用iconst指令,取值-128~127采用bipush指令,取值-32768~32767采用sipush指令,取值-2147483648~2147483647采用 ldc 指令。
先声明局部变量,再赋值为局部变量
程序
int i, j;
j = 200;
i = j;
字节码
0 sipush 200 压常量入栈
3 istore_2 弹出并赋值局部变量_2
4 iload_2 加载局部变量_2入栈
5 istore_1 弹出并赋值局部变量_1 即 i = j的语义实现
6 return
分析
(1)对于局部变量的相互赋值会在复制前把值对应的变量加载到栈中,使用iload指令
先声明局部变量,再连续赋值
程序
int i, j, k;
j = 200;
k = i = j;
字节码
0 sipush 200 压常量入栈
3 istore_2 弹出并赋值局部变量_2
4 iload_2 加载局部变量_2入栈
5 dup 复制栈顶,相当于iload_2执行了两次
6 istore_1 赋值给局部变量_1
7 istore_3 赋值给局部变量_3
8 return
分析
由上可知,
(1)对于连等于号,使用dup指令
(2)离值越近的越早赋值