jvm.go -- 设计和实现
zxhoo · · 3690 次点击 · · 开始浏览jvm.go
jvm.go是一个完全用Go语言实现的JVM,关于这个项目的发起原因和简单介绍可以看这篇文章。
最新进展和下一步计划
jvm.go的开发已经进行了一个半月了,除了HelloWorld和一些简单的Java代码以外,JUnit也可以正常运行了。下一步的计划是在jvm.go上把Jetty跑起来。下面介绍一下jvm.go的一些关键部分的设计和实现。
目录结构
- jvmgo jvm的go语言实现
- cmdline 这个包用来解析java命令行参数
- classfile 这个包把[]byte转化成ClassFile结构
- classpath 这个包实现了class文件查找
- native rt.jar里的本地方法实现
- jvm jvm核心功能
- instructions 指令集
- rtda 运行时数据区(Runtime Data Area),线程、堆栈、栈帧等都在这个包里
- class 类和对象(以及数组)等在这个包里
- class 类和对象(以及数组)等在这个包里
- testclasses 用来测试jvm的Java代码,Gradle项目
核心JVM
实现核心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微笑
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
jvm.go
jvm.go是一个完全用Go语言实现的JVM,关于这个项目的发起原因和简单介绍可以看这篇文章。
最新进展和下一步计划
jvm.go的开发已经进行了一个半月了,除了HelloWorld和一些简单的Java代码以外,JUnit也可以正常运行了。下一步的计划是在jvm.go上把Jetty跑起来。下面介绍一下jvm.go的一些关键部分的设计和实现。
目录结构
- jvmgo jvm的go语言实现
- cmdline 这个包用来解析java命令行参数
- classfile 这个包把[]byte转化成ClassFile结构
- classpath 这个包实现了class文件查找
- native rt.jar里的本地方法实现
- jvm jvm核心功能
- instructions 指令集
- rtda 运行时数据区(Runtime Data Area),线程、堆栈、栈帧等都在这个包里
- class 类和对象(以及数组)等在这个包里
- class 类和对象(以及数组)等在这个包里
- testclasses 用来测试jvm的Java代码,Gradle项目
核心JVM
实现核心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微笑