JVM的每一个线程都有一个虚拟机栈,方法调用时,JVM会在虚拟机栈内为该方法创建一个栈帧。

一条线程,只有正在执行的方法对应的栈帧时可活动的,这个栈帧被称为当前栈帧,当前栈帧对应的方法被称为当前方法,当前方法对应的类被称为当前类

任何对于局部变量表和操作数栈的操作,都是对当前栈帧的局部变量表和操作数栈的操作

方法开始时,栈帧入栈。方法结束时,栈帧出栈,栈帧把自己的执行结果传给前一个栈帧。

!!局部变量表中:long和double占2个位置(低32位先入,后32位后入),其他的都占一个位置。

!!操作数栈:long和double占2个位置(低32位占据index,高32位占据index+1),其他都占一个位置

操作数栈:有许多指令可以从操作数栈取出数据,操作数据,然后把操作结果重新入栈。

以下为代码实现

JTread类代表线程,StackFrame代表线程栈(虚拟机栈),ThreadStack为栈帧,Vars为局部变量表,OperandStack为操作数栈

以下探讨操作数栈中的double和long的存储

public void pushLong(long value) {//todo 向操作数栈中push一个long
int low32=(int)(value&0x00000000FFFFFFFF);
int high32=(int)(value>>32)&0x00000000FFFFFFFF;
if (top >= maxStackSize) throw new StackOverflowError();
slots[top].setValue(low32);
top++;
if (top >= maxStackSize) throw new StackOverflowError();
slots[top].setValue(high32);
top++;
} public long popLong() {//todo 从操作数栈顶pop一个long top--;
if (top < 0) throw new EmptyStackException();
int high=slots[top].getValue();
slots[top] = new Slot();
top--;
if (top < 0) throw new EmptyStackException();
int low=slots[top].getValue();
slots[top] = new Slot();
long result=((long)high<<32)|low;
return result;
} public void pushDouble(double value) {//todo
long longvalue=Double.doubleToLongBits(value);
int low32=(int)longvalue&0x00000000FFFFFFFF;
int high32=(int)(longvalue>>32)&0x00000000FFFFFFFF;
if (top >= maxStackSize) throw new StackOverflowError();
slots[top].setValue(low32);
top++;
if (top >= maxStackSize) throw new StackOverflowError();
slots[top].setValue(high32);
top++;
} public double popDouble() {//todo 从操作数栈顶pop一个double
top--;
if (top < 0) throw new EmptyStackException();
int high=slots[top].getValue();
slots[top]=new Slot();
top--;
if (top < 0) throw new EmptyStackException();
int low=slots[top].getValue();
slots[top] = new Slot();
long resultLong=((long)high<<32)|low;
return Double.longBitsToDouble(resultLong);
}

以下为vars中存储long和double的操作

 public void setLong(int index, long value) {
if (index < 0 || index >= maxSize) throw new IndexOutOfBoundsException();
int low=(int)(value&0x00000000FFFFFFFF);
int high=(int)((value>>32)&0x00000000FFFFFFFF);
varSlots[index].setValue(low);
varSlots[index+1].setValue(high);
} /**
* TODO:从局部变量表读取一个long类型变量
* @param index 变量的起始下标
* @return 变量的值
*/
public long getLong(int index){
if (index < 0 || index + 1 >= maxSize) throw new IndexOutOfBoundsException();
int low=varSlots[index].getValue();
int high=varSlots[index+1].getValue();
long result=((long)high<<32)|low;
return result;
} public void setDouble(int index, double value) {
if (index < 0 || index + 1 >= maxSize) throw new IndexOutOfBoundsException();
long longvalue=Double.doubleToLongBits(value);
int low32=(int)longvalue&0x00000000FFFFFFFF;
int high32=(int)(longvalue>>32)&0x00000000FFFFFFFF;
varSlots[index].setValue(low32);
varSlots[index+1].setValue(high32);
} public double getDouble(int index) {
if (index < 0 || index + 1 >= maxSize) throw new IndexOutOfBoundsException();
int low=varSlots[index].getValue();
int high=varSlots[index+1].getValue();
long resultLong=((long)high<<32)|low;
return Double.longBitsToDouble(resultLong);
}

DLOAD指令集

public class DLOAD extends Index8Instruction {
@Override
public void execute(StackFrame frame) {
System.out.println("执行了DLOAD的execute");
OperandStack stack=frame.getOperandStack();
Vars vars=frame.getLocalVars();
//一个double拆成两个int存在局部变量表中
int value1=vars.getInt(index);
int value2=vars.getInt(index+1);
long resultLong=((long)value2)<<32|value1;
double result=Double.longBitsToDouble(resultLong);
stack.pushDouble(result);
}
}

!!位运算要注意通过类型转换来扩充或减小位数

最新文章

  1. SqlServer之数据库三大范式
  2. EntityFramework 5.0 CodeFirst 教程04-查询,插入,更新,和删除数据
  3. HDU 5763 Another Meaning KMP+DP
  4. 46 关于Linux的I/O重定向
  5. (原创)speex与wav格式音频文件的互相转换(二)
  6. springMvc解决json中文乱码
  7. Activity和Servlet的相似之处和区别
  8. jquery于form正在使用submit问题,未解决
  9. 配置phonegap Android开发环境
  10. 教你如何一步步将项目部署到Github
  11. MySQL(十五)之数据备份中mysqldump详解
  12. 4.1 State Snapshot Transfer
  13. python程序—封装案例
  14. 最简单的spring boot web项目
  15. SQL Server代码段
  16. tomcat配置介绍
  17. Docker系列07:Docker-compose
  18. react全家桶-路由
  19. SkipList 跳跃表
  20. C语言学习笔记 (003) - C/C++中的实参和形参(转)

热门文章

  1. PHP set_file_buffer() 函数
  2. Java线程池的了解使用—筑基篇
  3. Idea快捷生成serialVersionUID
  4. 包管理Go module的使用
  5. 当asp.net core偶遇docker一(模型验证和Rabbitmq 三)
  6. C# Hello Word
  7. python3.3while循环
  8. 趣讲 PowerJob 超强大的调度层,开始表演真正的技术了
  9. [机器学习] keras:MNIST手写数字体识别(DeepLearning 的 HelloWord程序)
  10. golang的 strconv 包