Java 字节码技术详解( 五 )

..., value →..., value [,value]dup_x1 指令
官方说明是:复制栈顶的值,并将复制的值插入到最上面 2 个值的下方 。
操作数栈的值变化情况(方括号标识新插入的值):
..., value2, value1 →..., [value1,] value2, value1dup2_x1 指令
官方说明是:复制栈顶 1 个 64 位/或 2 个 32 位的值, 并将复制的值按照原始顺序,插入原始值下面一个 32 位值的下方 。
操作数栈的值变化情况(方括号标识新插入的值):
# 情景 1: value1, value2, and value3 都是分组 1 的值(32 位元素)..., value3, value2, value1 →..., [value2, value1,] value3, value2, value1# 情景 2: value1 是分组 2 的值(64 位,long 或double), value2 是分组 1 的值(32 位元素)..., value2, value1 →..., [value1,] value2, value1

Table 2.11.1-B 实际类型与 JVM 计算类型映射和分组
实际类型
JVM 计算类型
类型分组
boolean
int
1
byte
int
1
char
int
1
short
int
1
int
int
1
float
float
1
reference
reference
1
returnAddress
returnAddress
1
long
long
2
double
double
2
4.10 局部变量表
stack 主要用于执行指令,而局部变量则用来保存中间结果,两者之间可以直接交互 。
让我们编写一个复杂点的示例:
第一步,先编写一个计算移动平均数的类:
package demo.jvm0104;//移动平均数public class MovingAverage {private int count = 0;private double sum = 0.0D;public void submit(double value){this.count ++;this.sum += value;}public double getAvg(){if(0 == this.count){ return sum;}return this.sum/this.count;}}第二步,然后写一个类来调用:
package demo.jvm0104;public class LocalVariableTest {public static void main(String[] args) {MovingAverage ma = new MovingAverage();int num1 = 1;int num2 = 2;ma.submit(num1);ma.submit(num2);double avg = ma.getAvg();}}其中 main 方法中向 MovingAverage 类的实例提交了两个数值,并要求其计算当前的平均值 。
然后我们需要编译(还记得前面提到, 生成调试信息的 -g 参数吗) 。
javac -g demo/jvm0104/*.java然后使用 javap 反编译:
javap -c -verbose demo/jvm0104/LocalVariableTest看 main 方法对应的字节码:
public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=3, locals=6, args_size=10: new#2// class demo/jvm0104/MovingAverage3: dup4: invokespecial #3// Method demo/jvm0104/MovingAverage."<init>":()V7: astore_18: iconst_19: istore_210: iconst_211: istore_312: aload_113: iload_214: i2d15: invokevirtual #4// Method demo/jvm0104/MovingAverage.submit:(D)V18: aload_119: iload_320: i2d21: invokevirtual #4// Method demo/jvm0104/MovingAverage.submit:(D)V24: aload_125: invokevirtual #5// Method demo/jvm0104/MovingAverage.getAvg:()D28: dstore430: returnLineNumberTable:line 5: 0line 6: 8line 7: 10line 8: 12line 9: 18line 10: 24line 11: 30LocalVariableTable:StartLengthSlotNameSignature0310args[Ljava/lang/String;8231maLdemo/jvm0104/MovingAverage;10212num1I12193num2I3014avgD


推荐阅读