跳至主要內容

8、解释器

引领潮流大约 1 分钟手动编写jvm虚拟机jvmgo

执行指令集的调用者

指令集包含两部分 读取指令和执行

type Instruction interface {
	FetchOperands(reader *ByteCodeReader) // 从字节码流中取出操作数 输入变量
	Execute(frame *rtda.Frame)            // 执行指令逻辑
}

解释器是将指令以逻辑方式运行

//解释器 外部不能访问 私有方法
func interpret(methodInfo *classfile.MemberInfo){

	//获得method类 code属性
	codeAttr := methodInfo.CodeAttribute()
	maxLocals := codeAttr.MaxLocals()
	maxStack := codeAttr.MaxStack()
	bytecode := codeAttr.Code()

	thread := rtda.NewTread()
	frame  := thread.NewTestFrame(maxLocals,maxStack)

	thread.PushFrame(frame)

	defer catchErr(frame)
	loop(thread, bytecode)
}

//异常处理 因没有实现return指令 catch异常
func catchErr(frame *rtda.Frame){
	if r:=recover();r!=nil{
		fmt.Printf("LocalVars:%v
",frame.LocalVars())
		fmt.Printf("OperandStack:%v
",frame.OperandStack())
		fmt.Printf("no return fun 
")
		//panic(r)
	}
}

//loop执行循环所有方法
func loop(thread *rtda.Thread, bytecode []byte){

	frame:=thread.PopFrame()
	reader:= &base.ByteCodeReader{}

	for{
		//寻找下一个函数 计算pc
		pc:= frame.NextPC()
		thread.SetPC(pc)

		//设置初始值   解码指令
		reader.Reset(bytecode,pc)
		//读取指令集
		opcode:=reader.ReadUint8()
		//指令集转义
		inst:=instructions.NewInstruction(opcode)
		//读取变量
		inst.FetchOperands(reader)
		//获得下一个指令集便宜
		frame.SetNextPC(reader.PC())

		//excute   执行
		fmt.Printf("pc:%2d inst:%T %v
", pc, inst, inst)
		inst.Execute(frame)
	}

}

调用解释器

//测试解释器和指令集
func parseInterpret(cmd *Cmd) {
	cp := classpath.Parse(cmd.XjreOption, cmd.cpOption)
	className := strings.Replace(cmd.class, ".", "/", -1)
	//获得classfile
	cf := loadClass(className, cp)
	//获得main函数
	mainMethod:=getMainMethod(cf)
	if mainMethod != nil {
		//解释器执行
		interpret(mainMethod)
	}else{
		fmt.Printf("Main method not found in class %s
", cmd.class)
	}
}

//获得main函数
func getMainMethod(cf *classfile.ClassFile) *classfile.MemberInfo {

	for _, m := range cf.Methods() {
		if m.Name() == "main" && m.Descriptor() == "([Ljava/lang/String;)V" {
			return m
		}
	}

	return nil
}

shell脚本

go run main -test "interpret" -cp test/lib/example.jar jvmgo.book.ch05.GaussTest

实战项目地址

https://gitee.com/yinlingchaoliu/jvmgo.git