13 类初始化

2020-05-21  本文已影响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

类初始化触发情况

1、执行new指令创建类实例
2、执行putstatic、getstatic 指令存取类的静态变量
3、执行invokestatic调用静态方法
4、初始化一个类时,类的超类还没有初始化,要先初始化超类
5、执行某些反射操作

type Class struct{
//其他字段
    initStarted bool
}

func (self *Class) InitStarted() bool {
    return self.initStarted
}

// setter
func (self *Class) StartInit() {
    self.initStarted = true
}

初始化逻辑

在指令 putstatic、getstatic、new、invokestatic 添加初始化逻辑

    if !class.InitStarted() {
        frame.RevertNextPC()
        base.InitClass(frame.Thread(), class)
        return
    }
func (self *Frame) RevertNextPC() {
    self.nextPC = self.thread.pc
}

base逻辑

func InitClass(thread *rtda.Thread, class *heap.Class) {
    class.StartInit()             // 设置开始初始化标志
    scheduleClinit(thread, class) // 准备执行类初始化方法,push到栈顶,下一次执行的时候就会执行<cinit>
    initSuperClass(thread, class) // 循环初始化父类
}

func scheduleClinit(thread *rtda.Thread, class *heap.Class) {
    clinit := class.GetClinitMethod()
    if clinit != nil {
        // exec <clinit>
        newFrame := thread.NewFrame(clinit)
        thread.PushFrame(newFrame)
    }
}

func initSuperClass(thread *rtda.Thread, class *heap.Class) {
    if !class.IsInterface() {
        superClass := class.SuperClass()
        if superClass != nil && !superClass.InitStarted() {
            InitClass(thread, superClass)
        }
    }
}

实战项目地址

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

上一篇下一篇

猜你喜欢

热点阅读