13、类初始化
小于 1 分钟
类初始化触发情况
- 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