项目地址:https://github.com/gongxianshengjiadexiaohuihui
这个图就是线程私有的数据区结构
我们按照从外到内的方式来构建
线程Thread
package classfile.rtda;
/**
* @Author:ggp
* @Date:2019/2/13 14 27
* @Description:线程
*/
public class Thread {
/**
* 如果当前方法是java方法,存放正在执行的java虚拟机指令的地址,否则当前方法是本地方法,存放的值没有明确定义
*/
private int pc;
/**
* java虚拟机栈
*/
private Stack stack;
public Thread() {
/**
* 默认虚拟机栈可以存放1024个栈帧
*/
stack = new Stack(1024);
}
public int getPc() {
return pc;
}
public void setPc(int pc) {
this.pc = pc;
}
/**
* 进栈
* @param frame
*/
public void pushFrame(Frame frame){
stack.push(frame);
}
/**
* 出栈
* @return
*/
public Frame popFrame(){
return stack.pop();
}
/**
* 返回当前帧
* @return
*/
public Frame getCurrentFrame(){
return stack.top();
}
}
线程包含两个部分,一个pc计数器,用来存放正在执行指令的地址,一个jvm栈,用来执行指令,基本单位是栈帧,一帧相当于执行一次操作
jvm栈
package classfile.rtda;
import java.util.EmptyStackException;
/**
* @Author:ggp
* @Date:2019/2/13 14 28
* @Description:虚拟机栈
*/
public class Stack {
/**
* 最大容量
*/
private int maxSize;
/**
* 实际栈帧数量
*/
private int size;
/**
* 栈顶的帧
*/
private Frame top;
public Stack(int maxSize) {
this.maxSize = maxSize;
}
/**
* 进栈
* @param frame
*/
public void push(Frame frame){
if(size >= maxSize){
/**
* 如果栈已经满了,就抛出StackOverflowError错误
*/
throw new StackOverflowError();
}
if(top != null){
/**
* 如果栈顶不为空,就可以让新的栈帧把它压下去一个位置,把它保留在next位置
*/
frame.next = top;
}
top = frame;
size++;
}
/**
* 出栈
* @return
*/
public Frame pop(){
if(top == null){
/**
* 如果栈为空,就抛出EmptyStackException异常
*/
throw new EmptyStackException();
}
Frame tamp = top;
top = top.next;
tamp.next = null;
size--;
return tamp;
}
public Frame top(){
if(top == null){
/**
* 如果栈为空,就抛出EmptyStackException异常
*/
throw new EmptyStackException();
}
return top;
}
}
就是一个栈是由栈帧组成的链表,包含进栈出栈等操作
栈帧Frame
package classfile.rtda;
/**
* @Author:ggp
* @Date:2019/2/13 14 34
* @Description:
*/
public class Frame {
/**
* 指向相邻的下一个栈帧
*/
public Frame next;
/**
* 局部变量表
*/
private LocalVars localVars;
/**
* 操作数栈
*/
private OperandStack operandStack;
public Frame(int maxlocals, int maxStack){
localVars = new LocalVars(maxlocals);
operandStack = new OperandStack(maxStack);
}
public LocalVars getLocalVars() {
return localVars;
}
public OperandStack getOperandStack() {
return operandStack;
}
}
是一个链表的基本单位,包含局部变量表(用来存放计算过程中的变量和临时生成的变量),操作数栈(用来存放待计算的变量)
slot
package classfile.rtda;
/**
* @Author:ggp
* @Date:2019/2/13 14 23
* @Description:
* 局部变量表是按照索引访问的,所以可以把它想象成一个数组,根据虚拟机规范,这个数组每个元素至少可以容纳一个int,或引用值,两个连续的元素可以容纳一个一个long或double值
*/
public class Slot {
public int num;
public Object ref;
public Slot(){};
}
局部变量表和操作数栈的基本组成单位。可以存放一个基本类型或引用
引用
package classfile.rtda;
/**
* @Author:ggp
* @Date:2019/2/13 14 22
* @Description:作为对象引用
*/
public class Object {
}
局部变量表和操作数栈
package classfile.rtda;
/**
* @Author:ggp
* @Date:2019/2/13 15 04
* @Description:
*/
public class LocalVars {
private Slot[] localvars;
public LocalVars(int maxLocals){
if(maxLocals > 0){
localvars = new Slot[maxLocals];
}else {
throw new RuntimeException("maxLocal < 0");
}
}
/**
*局部变量表中存的数据是基本类型和引用,下面是他们的get set 方法
*/
public void setInt(int index, int val){
Slot slot = new Slot();
slot.num = val;
localvars[index] = slot;
}
public int getInt(int index){
return localvars[index].num;
}
public void setFloat(int index, float val){
Slot slot = new Slot();
slot.num = Float.floatToIntBits(val);
localvars[index] = slot;
}
public float getFloat(int index){
return Float.intBitsToFloat(localvars[index].num);
}
public void setLong(int index, long val){
/**
* 低32位
*/
Slot low = new Slot();
low.num = (int)val;
localvars[index] = low;
/**
* 高32位
*/
Slot high = new Slot();
high.num = (int)(val >> 32);
localvars[index + 1] = high;
}
public long getLong(int index){
/**
* 如果是负数,jvm会根据符号位扩展,填充32个1
*/
long low = (long)localvars[index].num & 0xffffffff;
long high = (long)localvars[index + 1].num << 32;
return high|low;
}
public void setDouble(int index, double val){
long num = Double.doubleToLongBits(val);
setLong(index,num);
}
public double getDouble(int index){
return Double.longBitsToDouble(getLong(index));
}
public void setRef(int index, Object ref){
Slot slot = new Slot();
slot.ref = ref;
localvars[index] = slot;
}
public Object getRef(int index){
return localvars[index].ref;
}
}
package classfile.rtda;
/**
* @Author:ggp
* @Date:2019/2/13 15 04
* @Description:
*/
public class OperandStack {
/**
* 栈顶元素在数组的位置(index),是基本类型,不初始化默认值是0
*/
private int size;
private Slot[] operandStack;
/**
*
* @param maxStack 操作栈的深度
*/
public OperandStack(int maxStack){
if(maxStack > 0){
operandStack = new Slot[maxStack];
}else{
throw new RuntimeException("maxStack < 0");
}
}
public void pushInt(int val){
Slot slot = new Slot();
slot.num = val;
operandStack[size++] = slot;
}
public int popInt(){
return operandStack[--size].num;
}
public void pushFloat(float val){
Slot slot = new Slot();
slot.num = Float.floatToIntBits(val);
operandStack[size++] =slot;
}
public float popFloat(){
return Float.intBitsToFloat(operandStack[--size].num);
}
public void pushLong(long val){
Slot low = new Slot();
low.num = (int)val;
operandStack[size++] = low;
Slot high = new Slot();
high.num = (int)(val >> 32);
operandStack[size++] = high;
}
public long popLong(){
long high = (long)operandStack[--size].num << 32;
long low = (long)operandStack[--size].num & 0xffffffff;
return high|low;
}
public void pushDouble(double val){
long num = Double.doubleToLongBits(val);
pushLong(num);
}
public double popDouble(){
return Double.longBitsToDouble(popLong());
}
public void pushRef(Object ref){
Slot slot = new Slot();
slot.ref = ref;
operandStack[size++] = slot;
}
public Object popRef(){
return operandStack[--size].ref;
}
}
都是有slot数组构成,说明它们存放的只能是基本类型或引用,需要注意的还是,jvm的符号位扩展问题
测试方法,修改Main类
import classfile.ClassFile;
import classfile.rtda.Frame;
import classfile.rtda.LocalVars;
import classfile.rtda.OperandStack;
import classpath.ClassPath;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import java.util.Arrays;
/**
* @ClassName Main
* @Description TODO
* @Author Mr.G
* @Date 2018/10/9 10:43
* @Version 1.0
*/
public class Main {
public static void main(String[] args){
Cmd cmd=new Cmd(args);
if(!cmd.isRightFmt||cmd.helpFlag){
cmd.printUsage();
}else if(cmd.versionFlag){
System.out.println("version 0.0.1");
}else{
startJVM(cmd);
}
}
public static void startJVM(Cmd cmd){
Frame frame = new Frame(100, 100);
testLocalVars(frame.getLocalVars());
testOperandStack(frame.getOperandStack());
}
public static void testLocalVars(LocalVars localVars){
localVars.setInt(0,100);
localVars.setInt(1, -100);
localVars.setLong(2, 299792580);
localVars.setLong(4,-299792580);
localVars.setFloat(6, (float) 3.12);
localVars.setFloat(7, (float)-3.12);
localVars.setDouble(8, 3.14159265358979);
localVars.setDouble(10, -3.14159265358979);
localVars.setRef(12, null);
System.out.println(localVars.getInt(0));
System.out.println(localVars.getInt(1));
System.out.println(localVars.getLong(2));
System.out.println(localVars.getLong(4));
System.out.println(localVars.getFloat(6));
System.out.println(localVars.getFloat(7));
System.out.println(localVars.getDouble(8));
System.out.println(localVars.getDouble(10));
System.out.println(localVars.getRef(12));
}
public static void testOperandStack(OperandStack operandStack){
operandStack.pushInt(100);
operandStack.pushInt(-100);
operandStack.pushLong(299792580);
operandStack.pushLong(-299792580);
operandStack.pushFloat((float) 3.12);
operandStack.pushFloat((float)-3.12);
operandStack.pushDouble(3.14159265358979);
operandStack.pushDouble(-3.14159265358979);
operandStack.pushRef(null);
System.out.println(operandStack.popRef());
System.out.println(operandStack.popDouble());
System.out.println(operandStack.popDouble());
System.out.println(operandStack.popFloat());
System.out.println(operandStack.popFloat());
System.out.println(operandStack.popLong());
System.out.println(operandStack.popLong());
System.out.println(operandStack.popInt());
System.out.println(operandStack.popInt());
}
}
测试结果