一、运行时数据区
https://blog.csdn.net/u011464536/article/details/78235438
二、实现
在jvmgo文件夹下面创建rtda文件夹,并在里面创建object.go文件
1 package rtda 2 3 type Object struct { 4 // todo 5 }
1、线程
创建thread.go文件
1 package rtda 2 3 /* 4 JVM 5 Thread 6 pc 7 Stack 8 Frame 9 LocalVars 10 OperandStack 11 */ 12 type Thread struct { 13 pc int // the address of the instruction currently being executed 14 stack *Stack 15 // todo 16 } 17 18 func NewThread() *Thread { 19 return &Thread{ 20 stack: newStack(1024), 21 } 22 } 23 24 func (self *Thread) PC() int { 25 return self.pc 26 } 27 func (self *Thread) SetPC(pc int) { 28 self.pc = pc 29 } 30 31 func (self *Thread) PushFrame(frame *Frame) { 32 self.stack.push(frame) 33 } 34 func (self *Thread) PopFrame() *Frame { 35 return self.stack.pop() 36 } 37 38 func (self *Thread) CurrentFrame() *Frame { 39 return self.stack.top() 40 }
定义了pc和stack字段,stack是Stack结构体的指针。NewThread()创建Thread实例,newStack()创建Stack结构体实例,参数表示要创建的Stack最多容纳多少帧,PushFrame()和PopFrame()方法调用Stack结构体的相应方法。CurrentFrame()方法返回当前帧。
2、java虚拟机栈
创建jvm_stack.go文件
1 package rtda 2 3 // jvm stack 4 type Stack struct { 5 maxSize uint 6 size uint 7 _top *Frame // stack is implemented as linked list 8 } 9 10 func newStack(maxSize uint) *Stack { 11 return &Stack{ 12 maxSize: maxSize, 13 } 14 } 15 16 func (self *Stack) push(frame *Frame) { 17 if self.size >= self.maxSize { 18 panic("java.lang.StackOverflowError") 19 } 20 21 if self._top != nil { 22 frame.lower = self._top 23 } 24 25 self._top = frame 26 self.size++ 27 } 28 29 func (self *Stack) pop() *Frame { 30 if self._top == nil { 31 panic("jvm stack is empty!") 32 } 33 34 top := self._top 35 self._top = top.lower 36 top.lower = nil 37 self.size-- 38 39 return top 40 } 41 42 func (self *Stack) top() *Frame { 43 if self._top == nil { 44 panic("jvm stack is empty!") 45 } 46 47 return self._top 48 }
maxSize保存栈的容量,size是当前大小,_top字段保存栈顶指针。其他函数不做解释。
3、帧
建立frame.go文件
1 package rtda 2 3 // stack frame 4 type Frame struct { 5 lower *Frame // stack is implemented as linked list 6 localVars LocalVars 7 operandStack *OperandStack 8 // todo 9 } 10 11 func NewFrame(maxLocals, maxStack uint) *Frame { 12 return &Frame{ 13 localVars: newLocalVars(maxLocals), 14 operandStack: newOperandStack(maxStack), 15 } 16 } 17 18 // getters 19 func (self *Frame) LocalVars() LocalVars { 20 return self.localVars 21 } 22 func (self *Frame) OperandStack() *OperandStack { 23 return self.operandStack 24 }
lower用来实现链表数据结构,localVars字段保存局部变量表指针,operandStack字段保存操作数栈指针。
4、局部变量表
创建slot.go文件。
1 package rtda 2 3 type Slot struct { 4 num int32 5 ref *Object 6 }
num字段存放整数,ref存放引用。
创建local_vars.go文件
1 package rtda 2 3 import "math" 4 5 type LocalVars []Slot 6 7 func newLocalVars(maxLocals uint) LocalVars { 8 if maxLocals > 0 { 9 return make([]Slot, maxLocals) 10 } 11 return nil 12 } 13 14 func (self LocalVars) SetInt(index uint, val int32) { 15 self[index].num = val 16 } 17 func (self LocalVars) GetInt(index uint) int32 { 18 return self[index].num 19 } 20 21 func (self LocalVars) SetFloat(index uint, val float32) { 22 bits := math.Float32bits(val) 23 self[index].num = int32(bits) 24 } 25 func (self LocalVars) GetFloat(index uint) float32 { 26 bits := uint32(self[index].num) 27 return math.Float32frombits(bits) 28 } 29 30 // long consumes two slots 31 func (self LocalVars) SetLong(index uint, val int64) { 32 self[index].num = int32(val) 33 self[index+1].num = int32(val >> 32) 34 } 35 func (self LocalVars) GetLong(index uint) int64 { 36 low := uint32(self[index].num) 37 high := uint32(self[index+1].num) 38 return int64(high)<<32 | int64(low) 39 } 40 41 // double consumes two slots 42 func (self LocalVars) SetDouble(index uint, val float64) { 43 bits := math.Float64bits(val) 44 self.SetLong(index, int64(bits)) 45 } 46 func (self LocalVars) GetDouble(index uint) float64 { 47 bits := uint64(self.GetLong(index)) 48 return math.Float64frombits(bits) 49 } 50 51 func (self LocalVars) SetRef(index uint, ref *Object) { 52 self[index].ref = ref 53 } 54 func (self LocalVars) GetRef(index uint) *Object { 55 return self[index].ref 56 }
对不同的变量有不同的存取方法。
5、操作数栈
与局部变量表的实现方法类似。创建operand_stack.go文件
1 package rtda 2 3 import "math" 4 5 type OperandStack struct { 6 size uint 7 slots []Slot 8 } 9 10 func newOperandStack(maxStack uint) *OperandStack { 11 if maxStack > 0 { 12 return &OperandStack{ 13 slots: make([]Slot, maxStack), 14 } 15 } 16 return nil 17 } 18 19 func (self *OperandStack) PushInt(val int32) { 20 self.slots[self.size].num = val 21 self.size++ 22 } 23 func (self *OperandStack) PopInt() int32 { 24 self.size-- 25 return self.slots[self.size].num 26 } 27 28 func (self *OperandStack) PushFloat(val float32) { 29 bits := math.Float32bits(val) 30 self.slots[self.size].num = int32(bits) 31 self.size++ 32 } 33 func (self *OperandStack) PopFloat() float32 { 34 self.size-- 35 bits := uint32(self.slots[self.size].num) 36 return math.Float32frombits(bits) 37 } 38 39 // long consumes two slots 40 func (self *OperandStack) PushLong(val int64) { 41 self.slots[self.size].num = int32(val) 42 self.slots[self.size+1].num = int32(val >> 32) 43 self.size += 2 44 } 45 func (self *OperandStack) PopLong() int64 { 46 self.size -= 2 47 low := uint32(self.slots[self.size].num) 48 high := uint32(self.slots[self.size+1].num) 49 return int64(high)<<32 | int64(low) 50 } 51 52 // double consumes two slots 53 func (self *OperandStack) PushDouble(val float64) { 54 bits := math.Float64bits(val) 55 self.PushLong(int64(bits)) 56 } 57 func (self *OperandStack) PopDouble() float64 { 58 bits := uint64(self.PopLong()) 59 return math.Float64frombits(bits) 60 } 61 62 func (self *OperandStack) PushRef(ref *Object) { 63 self.slots[self.size].ref = ref 64 self.size++ 65 } 66 func (self *OperandStack) PopRef() *Object { 67 self.size-- 68 ref := self.slots[self.size].ref 69 self.slots[self.size].ref = nil 70 return ref 71 }
三、测试
在main.go中加入import “jvmgo/rtda"
修改startJVM()方法
1 func startJVM(cmd *Cmd) { 2 frame := rtda.NewFrame(100, 100) 3 testLocalVars(frame.LocalVars()) 4 testOperandStack(frame.OperandStack()) 5 } 6 7 func testLocalVars(vars rtda.LocalVars) { 8 vars.SetInt(0, 100) 9 vars.SetInt(1, -100) 10 vars.SetLong(2, 2997924580) 11 vars.SetLong(4, -2997924580) 12 vars.SetFloat(6, 3.1415926) 13 vars.SetDouble(7, 2.71828182845) 14 vars.SetRef(9, nil) 15 println(vars.GetInt(0)) 16 println(vars.GetInt(1)) 17 println(vars.GetLong(2)) 18 println(vars.GetLong(4)) 19 println(vars.GetFloat(6)) 20 println(vars.GetDouble(7)) 21 println(vars.GetRef(9)) 22 } 23 24 func testOperandStack(ops *rtda.OperandStack) { 25 ops.PushInt(100) 26 ops.PushInt(-100) 27 ops.PushLong(2997924580) 28 ops.PushLong(-2997924580) 29 ops.PushFloat(3.1415926) 30 ops.PushDouble(2.71828182845) 31 ops.PushRef(nil) 32 println(ops.PopRef()) 33 println(ops.PopDouble()) 34 println(ops.PopFloat()) 35 println(ops.PopLong()) 36 println(ops.PopLong()) 37 println(ops.PopInt()) 38 println(ops.PopInt()) 39 }
在命令行窗口执行 go install jvmgo,编译成功后对jvmgo.exe进行测试
PS D:Program_Filesgoin> .jvmgo.exe test 100 -100 2997924580 -2997924580 +3.141593e+000 +2.718282e+000 0x0 0x0 +2.718282e+000 +3.141593e+000 -2997924580 2997924580 -100 100