美文网首页
15、jvm支持字符串-数组扩展

15、jvm支持字符串-数组扩展

作者: 陈桐Caliburn | 来源:发表于2020-05-22 11:17 被阅读0次

    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

    采用hook方式生成字符串
    1、加载java/lang/String => jstr
    2、ClassLoader加载'[C' char数组
    3、将go 字符串utf-8 转换为 java utf-16格式
    3、反射修改string value字段

    // go string -> java.lang.String
    func JString(loader *ClassLoader, goStr string) *Object {
        if internedStr, ok := internedStrings[goStr]; ok {
            return internedStr
        }
    
        //go 字符串 utf-8 => java utf-16
        chars := stringToUtf16(goStr)
    
        //加载 java类 char数组
        jChars := &Object{loader.LoadClass("[C"), chars}
    
        //加载java类 String
        jStr := loader.LoadClass("java/lang/String").NewObject()
    
        //反射设置
        jStr.SetRefVar("value", "[C", jChars)
    
        internedStrings[goStr] = jStr
        return jStr
    }
    

    反射支持

    
    object.go
    
    func (self *Object) GetRefVar(name, descriptor string) *Object {
        field := self.class.getField(name, descriptor, false)
        slots := self.data.(Slots)
        return slots.GetRef(field.slotId)
    }
    
    func (self *Object) SetRefVar(name, descriptor string, ref *Object) {
        field := self.class.getField(name, descriptor, false)
        slots := self.data.(Slots)
        slots.SetRef(field.slotId, ref)
    }
    
    class.go
    func (self *Class) getField(name, descriptor string, isStatic bool) *Field {
        for c := self; c != nil; c = c.superClass {
            for _, field := range c.fields {
                if field.IsStatic() == isStatic &&
                    field.name == name &&
                    field.descriptor == descriptor {
    
                    return field
                }
            }
        }
        return nil
    }
    
    // todo 支持反射 reflection
    func (self *Class) GetRefVar(fieldName, fieldDescriptor string) *Object {
        field := self.getField(fieldName, fieldDescriptor, true)
        return self.staticVars.GetRef(field.slotId)
    }
    
    func (self *Class) SetRefVar(fieldName, fieldDescriptor string, ref *Object) {
        field := self.getField(fieldName, fieldDescriptor, true)
        self.staticVars.SetRef(field.slotId, ref)
    }
    
    

    idc扩展

    //todo 特别支持
        case string:  //todo 支持字符串 压栈
            internedStr := heap.JString(class.Loader(),c.(string))
            stack.PushRef(internedStr)
    
    

    classloader扩展

    func initStaticFinalVar(){
    
    case "Ljava/lang/String;": //todo 支持字符串
                goStr := cp.GetConstant(cpIndex).(string)
                jStr := JString(class.Loader(),goStr)
                vars.SetRef(slotId,jStr)
            }
    }
    

    字符串测试

    
    func Interpret(){
        //字符串参数
        jArgs := createArgsArray(method.Class().Loader(),args)
        frame.LocalVars().SetRef(0,jArgs)
    }
    
    //创建args数组
    func createArgsArray(loader *heap.ClassLoader, args []string) *heap.Object {
        //加载class类
        stringClass := loader.LoadClass("java/lang/String")
        argsArr := stringClass.ArrayClass().NewArray(uint(len(args)))
        jArgs := argsArr.Refs()
        for i, arg := range args {
            jArgs[i] = heap.JString(loader, arg)
        }
        return argsArr
    }
    

    shell脚本

    #测试字符串数组
    go run main   -test "string"  -cp test/lib/example.jar   jvmgo.book.ch01.HelloWorld
    #测试字符串参数
    go run main   -test "string"  -cp test/lib/example.jar   jvmgo.book.ch08.PrintArgs  'go jvm args' 'PrintArgs' 'Hello , World'
    

    实战项目地址

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

    提交标签 "array"

    相关文章

      网友评论

          本文标题:15、jvm支持字符串-数组扩展

          本文链接:https://www.haomeiwen.com/subject/ouxqahtx.html