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

实战项目地址

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

上一篇 下一篇

猜你喜欢

热点阅读