..., value →..., value [,value]
dup_x1 指令
官方说明是:复制栈顶的值,并将复制的值插入到最上面 2 个值的下方 。
操作数栈的值变化情况(方括号标识新插入的值):
..., value2, value1 →..., [value1,] value2, value1
dup2_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
推荐阅读
- MyBatis自动生成工具,开发编码好帮手
- Python 常用的十行代码,建议收藏
- 绕过rar密码提取文件怎么操作?
- Java,OpenCV,图像阈值分割,阈值化,二值阈值化、截断阈值化等
- nest.js + sms 实现短信验证码登录
- 如何在开发中规避硬编码
- 十分钟搞懂手机号码一键登录
- 每天敲代码不到 1 小时,程序员每天都在做什么?
- 无代码系统搭建排班管理应用
- Java 日志记录—记录什么和不记录什么?