8、解释器
2020-05-03 本文已影响0人
陈桐Caliburn
gojvm目录
1、搭建go环境
2、cmd命令行参数解析
3、搜索class文件
4、添加testOption 便于单元测试
5、解析classfile文件
6、运行时数据区
7、指令集
8、解释器
9、创建Class
10、类加载器
11、对象实例化new object
12、方法调用和返回
13 类初始化
14、jvm支持数组
15、jvm支持字符串-数组扩展
16、本地方法调用
17、ClassLoader原理
18、异常处理
19、 启动jvm
执行指令集的调用者
指令集包含两部分 读取指令和执行
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\n",frame.LocalVars())
fmt.Printf("OperandStack:%v\n",frame.OperandStack())
fmt.Printf("no return fun \n")
//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\n", 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\n", 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