这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战
运行时数据区概述
Java虚拟机规范把这些内存区域叫作运行时数据区。运行时数据区可以分为两类:一类是多线程共享的,另一类则是线程私有的。
多线程共享的内存区域主要存放两类数据:类数据和类实例(也就是对象)。对象数据存放在堆(Heap)中,类数据存放在方法区(Method Area)中。 每个线程都有自己的pc寄存器(Program Counter)和Java虚拟机栈(JVMStack)。Java虚拟机栈又由栈帧(Stack Frame,后面简称帧)构成,帧中保存方法执行的状态,包括局部变量表(Local Variable)和操作数栈(Operand Stack)等。
代码
线程
/**
* @Author blackcat
* @create 2021/8/12 15:28
* @version: 1.0
* @description:线程
*/
public class JThread {
//Program Counter 寄存器
private int pc;
//虚拟机栈
private JvmStack stack;
public JThread(){
this.stack = new JvmStack(1024);
}
public int pc(){
return this.pc;
}
public void setPC(int pc){
this.pc = pc;
}
public void pushFrame(Frame frame){
this.stack.push(frame);
}
public Frame popFrame(){
return this.stack.pop();
}
public Frame currentFrame(){
return this.stack.top();
}
}
复制代码
虚拟机栈
Java 虚拟机栈(Java Virtual Machine Stacks),早期也叫 Java 栈。每个线程在创建的时候都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次 Java 方法调用,是线程私有的,生命周期和线程一致。
/**
* @Author blackcat
* @create 2021/8/12 15:28
* @version: 1.0
* @description:虚拟机栈
*/
public class JvmStack {
//栈的容量,最多可以容纳多少帧
private int maxSize;
//栈的当前大小
private int size;
//栈顶指针
private Frame _top;
public JvmStack(int maxSize) {
this.maxSize = maxSize;
}
//帧推入栈顶
public void push(Frame frame) {
//如果栈已经满了,StackOverflowError异常
if (this.size > this.maxSize) {
throw new StackOverflowError();
}
if (this._top != null) {
frame.lower = this._top;
}
this._top = frame;
this.size++;
}
public Frame pop() {
if (this._top == null) {
throw new RuntimeException("jvm stack is empty!");
}
Frame top = this._top;
this._top = top.lower;
top.lower = null;
this.size--;
return top;
}
public Frame top(){
if (this._top == null){
throw new RuntimeException("jvm stack is empty!");
}
return this._top;
}
}
复制代码
栈帧
每个栈帧(Stack Frame)中存储着:
局部变量表(Local Variables)
操作数栈(Operand Stack)(或称为表达式栈)
动态链接(Dynamic Linking):指向运行时常量池的方法引用
方法返回地址(Return Address):方法正常退出或异常退出的地址
一些附加信息
本例只包含前面两个
/**
* @Author blackcat
* @create 2021/8/12 15:29
* @version: 1.0
* @description:栈帧
*/
public class Frame {
//stack is implemented as linked list
Frame lower;
//局部变量表
private LocalVars localVars;
//操作数栈
private OperandStack operandStack;
public Frame(int maxLocals, int maxStack) {
this.localVars = new LocalVars(maxLocals);
this.operandStack = new OperandStack(maxStack);
}
public LocalVars localVars(){
return localVars;
}
public OperandStack operandStack(){
return operandStack;
}
}
复制代码
局部变量
/**
* @Author blackcat
* @create 2021/8/12 15:32
* @version: 1.0
* @description:局部变量表
*/
public class LocalVars {
private Slot[] localVars;
public LocalVars(int maxLocals) {
if (maxLocals > 0) {
localVars = new Slot[maxLocals];
for (int i = 0; i < maxLocals; i++) {
localVars[i] = new Slot();
}
}
}
public void setInt(int pos, int val) {
checkIndex(pos);
localVars[pos].num = val;
}
public int getInt(int pos) throws NoSuchElementException {
checkIndex(pos);
return localVars[pos].num;
}
public void setFloat(int pos, float val) {
checkIndex(pos);
localVars[pos].num = Float.floatToIntBits(val);
}
public Float getFloat(int pos) {
checkIndex(pos);
return Float.intBitsToFloat(localVars[pos].num);
}
public void setLong(int pos, long val) {
checkIndex(pos + 1);
int[] ints = ByteUtil.long2IntArr(val);
localVars[pos].num = ints[0];
localVars[pos + 1].num = ints[1];
}
public long getLong(int pos) {
checkIndex(pos + 1);
return ByteUtil.int2Long(localVars[pos].num, localVars[pos + 1].num);
}
public void setDouble(int pos, double val) {
checkIndex(pos);
long l = Double.doubleToLongBits(val);
setLong(pos, l);
}
public double getDouble(int pos) {
long res = getLong(pos);
return Double.longBitsToDouble(res);
}
public void setRef(int pos, Object ref) {
checkIndex(pos);
localVars[pos].ref = ref;
}
public Object getRef(int pos) {
checkIndex(pos);
return localVars[pos].ref;
}
private void checkIndex(int pos) {
if (pos < 0 || pos >= size()) {
throw new IllegalArgumentException("invalid index, " + pos);
}
}
public int size() {
return localVars.length;
}
}
复制代码
操作数栈
/**
* @Author blackcat
* @create 2021/8/12 15:33
* @version: 1.0
* @description:操作数栈
*/
public class OperandStack {
private int size = 0;
private Slot[] operands;
public OperandStack(int size) {
operands = new Slot[size];
for (int i = 0; i < size; i++) {
operands[i] = new Slot();
}
}
public void pushInt(int val) {
operands[size].num = val;
size++;
}
public int popInt() {
size--;
return operands[size].num;
}
public void pushRef(Object val) {
operands[size].ref = val;
size++;
}
public Object popRef() {
size--;
Object val = operands[size].ref;
operands[size].ref = null;
return val;
}
public void pushFloat(float val) {
operands[size].num = Float.floatToIntBits(val);
size++;
}
public Float popFloat() {
--size;
return Float.intBitsToFloat(operands[size].num);
}
public void pushLong(long val) {
int[] ints = ByteUtil.long2IntArr(val);
operands[size++].num = ints[0];
operands[size++].num = ints[1];
}
public long popLong() {
size--;
size--;
return ByteUtil.int2Long(operands[size].num, operands[size + 1].num);
}
public void pushDouble(double val) {
long res = Double.doubleToLongBits(val);
pushLong(res);
}
public double popDouble() {
long res = popLong();
return Double.longBitsToDouble(res);
}
}
/**
* @Author blackcat
* @create 2021/8/12 15:33
* @version: 1.0
* @description:数据槽
*/
public class Slot {
int num;
Object ref;
}
复制代码
测试
import com.black.cat.jvm.rtda.Frame;
import com.black.cat.jvm.rtda.LocalVars;
import com.black.cat.jvm.rtda.OperandStack;
/**
* @Author blackcat
* @create 2021/8/11 13:43
* @version: 1.0
* @description:命令行工具
*/
public class Main {
public static void main(String[] args) {
String[] argv = {"-classpath", "D:\\develop\\code\\jjvm\\jvm-03\\target\\classes", "com.black.cat.jvm.MainTest"};
Cmd cmd = Cmd.parse(argv);
if (!cmd.ok || cmd.helpFlag) {
System.out.println("Usage: <main class> [-options] class [args...]");
return;
}
if (cmd.versionFlag) {
System.out.println("java version \"1.8.0\"");
return;
}
startJVM(cmd);
}
private static void startJVM(Cmd args) {
Frame frame = new Frame(100, 100);
test_localVars(frame.localVars());
test_operandStack(frame.operandStack());
}
private static void test_localVars(LocalVars vars){
vars.setInt(0,100);
vars.setInt(1,-100);
vars.setLong(2, 2997924580L);
vars.setLong(4, -2997924580L);
vars.setFloat(6, 3.1415926F);
vars.setDouble(7, 2.71828182845);
vars.setRef(9, null);
System.out.println(vars.getInt(0));
System.out.println(vars.getInt(1));
System.out.println(vars.getLong(2));
System.out.println(vars.getLong(4));
System.out.println(vars.getFloat(6));
System.out.println(vars.getDouble(7));
System.out.println(vars.getRef(9));
}
private static void test_operandStack(OperandStack ops){
ops.pushInt(100);
ops.pushInt(-100);
ops.pushLong(2997924580L);
ops.pushLong(-2997924580L);
ops.pushFloat(3.1415926F);
ops.pushDouble(2.71828182845);
ops.pushRef(null);
System.out.println(ops.popRef());
System.out.println(ops.popDouble());
System.out.println(ops.popFloat());
System.out.println(ops.popLong());
System.out.println(ops.popLong());
System.out.println(ops.popInt());
System.out.println(ops.popInt());
}
}
复制代码
结果
备注:float 存在一些精度问题
100
-100
2997924580
-2997924580
3.1415925
2.71828182845
null
null
2.71828182845
3.1415925
-2997924580
2997924580
-100
100
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END