跳至主要內容

13、类初始化

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

类初始化触发情况

  • 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://gitee.com/yinlingchaoliu/jvmgo.git