jvm.go是一个完全用Go语言实现的JVM,关于这个项目的发起原因和简单介绍可以看这篇文章。

jvm.go的开发已经进行了一个半月了,除了HelloWorld和一些简单的Java代码以外,JUnit也可以正常运行了。下一步的计划是在jvm.go上把Jetty跑起来。下面介绍一下jvm.go的一些关键部分的设计和实现。

实现核心JVM其实是相对比较简单的,对照着JVM规范,把Thread、Frame、Operand Stack、Local Vars、Class、Object、Array、指令集等一一实现就可以了。下面以FrameStack和OperandStack为例,简单介绍一下:
type Stack struct {
maxSize uint
size uint
_top *Frame // stack is implemented as linked list
}type OperandStack struct {
size uint
slots []Any
}FrameStack是用链表(LinkedList)实现的,OperandStack内部其实用了Slice。
为了更好的代码可读性,每一个指令都实现成一了个struct,下面是iinc指令的完整代码:
package instructions
import "jvmgo/jvm/rtda"
// Increment local variable by constant
type iinc struct {
index uint
_const int32
}
func (self *iinc) fetchOperands(decoder *InstructionDecoder) {
self.index = uint(decoder.readUint8())
self._const = int32(decoder.readInt8())
}
func (self *iinc) Execute(frame *rtda.Frame) {
localVars := frame.LocalVars()
val := localVars.GetInt(self.index)
val += self._const
localVars.SetInt(self.index, val)
}
因为大部分指令都是需要操作OperandStack和/或LocalVars的,所以指令的Execute方法参数设计接收为*Frame类型的参数:type Instruction interface {
fetchOperands(decoder *InstructionDecoder)
Execute(frame *rtda.Frame)
}
最初开始写jvm.go的时候,用的是OpenJDK的rt.jar。但是因为要经常查看rt.jar的Java代码,用IDE可以直接跳进Oracle JDK的rt.jar代码里。所以为了方便,后来就改为针对Oracle的rt.jar进行开发。rt.jar里有几千个本地方法,目前为止,只实现了不到100个。下面是本地方法的类型定义:
type NativeMethod func(frame *rtda.Frame)
Go本身就是垃圾回收语言,所以jvm.go没有单独实现垃圾回收机制。
jvm.go把每个Java线程都映射为一个goroutine,下面是Thread.start0()本地方法的实现代码:
// private native void start0();
// ()V
func start0(frame *rtda.Frame) {
vars := frame.LocalVars()
this := vars.GetThis()
newThread := rtda.NewThread(this)
runMethod := this.Class().GetInstanceMethod("run", "()V")
newFrame := newThread.NewFrame(runMethod)
newFrame.LocalVars().SetRef(0, this)
newThread.PushFrame(newFrame)
this.LockState()
this.SetExtra(newThread)
this.UnlockState()
go interpreter.Loop(newThread)
}
jvm.go已经有了很大的进展,但是离完整的JVM实现还差的很远。希望对Java和JVM,或者Go语言感兴趣的朋友可以review代码,甚至贡献代码。希望jvm.go有朝一日能够成为一个正真的jvm,一个有用的jvm
原文地址:http://blog.csdn.net/zxhoo/article/details/44104553