9、创建Class
2020-05-05 本文已影响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
知识扩展
方法区存储类信息
创建Class
1、存储类信息
2、常量池转化为运行时常量池
1、从classFile读取信息,拷贝到类中
Class
type Class struct {
accessFlags uint16 // 类访问标志
name string // 类名(全限定)
superClassName string // 父类名(全限定),eg. java/lang/Object
interfaceNames []string // 接口名(全限定)
constantPool *ConstantPool // 运行时常量池
fields []*Field // 字段表
methods []*Method // 方法表
loader *ClassLoader // 类加载器
superClass *Class // 父类指针
interfaces []*Class // 实现的接口指针
instanceSlotCount uint // 存放实例变量占据的空间大小(包含从父类继承来的实例变量)(其中long和double占两个slot)
staticSlotCount uint // 存放类变量占据的空间大小(只包含当前类的类变量)(其中long和double占两个slot)
staticVars Slots // 存放静态变量
initStarted bool
}
1、创建class实例总方法
func newClass(cf *classfile.ClassFile) *Class {
class := &Class{}
class.accessFlags = cf.AccessFlags()
class.name = cf.ClassName()
class.superClassName = cf.SuperClassName()
class.interfaceNames = cf.InterfaceNames()
class.constantPool = newConstantPool(class, cf.ConstantPool())
class.fields = newFields(class, cf.Fields())
class.methods = newMethods(class, cf.Methods())
return class
}
公共字段信息 (访问标志,访问名字,描述符)
// Field 与 Method 的父类,不是 Class 的父类
type ClassMember struct {
accessFlags uint16
name string
descriptor string
class *Class // 所属的类
}
// 从 classFile 中复制数据
func (self *ClassMember) copyMemberInfo(memberInfo *classfile.MemberInfo) {
self.accessFlags = memberInfo.AccessFlags()
self.name = memberInfo.Name()
self.descriptor = memberInfo.Descriptor()
}
// d 是否可以访问 self(字段或方法)
func (self *ClassMember) isAccessibleTo(d *Class) bool {
// self 是 public
if self.IsPublic() {
return true
}
c := self.class
// self 是 protected,则只有 d 是 self所在的class c的子类或者同一个包可以访问
// 注意 protected 不只是子类级别,同包也可访问
if self.IsProtected() {
return d == c || d.isSubClassOf(c) || c.getPackageName() == d.getPackageName()
}
// self 是 default 级别
if !self.IsPrivate() {
return c.getPackageName() == d.getPackageName()
}
return d == c
}
根据 classFile 创建 字段表
type Field struct {
ClassMember
constantValueIndex uint
slotId uint
}
// 根据 classFile 创建 字段表
func newFields(class *Class, cfFields []*classfile.MemberInfo) []*Field {
fields := make([]*Field, len(cfFields))
for i, cfField := range cfFields {
fields[i] = &Field{}
fields[i].class = class
fields[i].copyMemberInfo(cfField)
fields[i].copyAttributes(cfField)
}
return fields
}
根据 classFile 创建 方法表
type Method struct {
ClassMember
maxStack uint
maxLocals uint
code []byte // 方法字节码表
argSlotCount uint // 参数个数
}
func newMethods(class *Class, cfMethods []*classfile.MemberInfo) []*Method {
methods := make([]*Method, len(cfMethods))
for i, cfMethod := range cfMethods {
methods[i] = &Method{}
methods[i].class = class
methods[i].copyMemberInfo(cfMethod)
methods[i].copyAttributes(cfMethod)
methods[i].calArgSlotCount()
}
return methods
}
2、把 classFile 中的常量池转化为运行时常量池
将[]classfile.ConstantInfo 转化为[]heap.Constant
取值通过常量池来获得
// 常量项
type Constant interface{}
// 运行时常量池
type ConstantPool struct {
class *Class // 所属的类
consts []Constant
}
//创建运行时常量池 []consts
func newConstantPool(class *Class, cfCp classfile.ConstantPool) *ConstantPool {
cpCount := len(cfCp)
consts := make([]Constant, cpCount)
rtCp := &ConstantPool{class, consts}
for i := 1; i < cpCount; i++ {
cpInfo := cfCp[i]
switch cpInfo.(type) {
// 字面量:整数、浮点数、字符串
case *classfile.ConstantIntegerInfo:
consts[i] = cpInfo.(*classfile.ConstantIntegerInfo).Value()
case *classfile.ConstantFloatInfo:
consts[i] = cpInfo.(*classfile.ConstantFloatInfo).Value()
case *classfile.ConstantLongInfo:
consts[i] = cpInfo.(*classfile.ConstantLongInfo).Value()
i++
case *classfile.ConstantDoubleInfo:
consts[i] = cpInfo.(*classfile.ConstantDoubleInfo).Value()
i++
case *classfile.ConstantStringInfo:
consts[i] = cpInfo.(*classfile.ConstantStringInfo).String()
// 符号引用:类、字段、方法、接口方法
case *classfile.ConstantClassInfo:
classInfo := cpInfo.(*classfile.ConstantClassInfo)
consts[i] = newClassRef(rtCp, classInfo)
case *classfile.ConstantFieldrefInfo:
fieldrefInfo := cpInfo.(*classfile.ConstantFieldrefInfo)
consts[i] = newFieldRef(rtCp, fieldrefInfo)
case *classfile.ConstantMethodrefInfo:
methodrefInfo := cpInfo.(*classfile.ConstantMethodrefInfo)
consts[i] = newMethodRef(rtCp, methodrefInfo)
case *classfile.ConstantInterfaceMethodrefInfo:
interfaceMethodrefInfo := cpInfo.(*classfile.ConstantInterfaceMethodrefInfo)
consts[i] = newInterfaceMethodRef(rtCp, interfaceMethodrefInfo)
}
}
return rtCp
}
// 根据索引返回常量项 取值
func (self *ConstantPool) GetConstant(index uint) Constant {
if c := self.consts[index]; c != nil {
return c
}
panic(fmt.Sprintf("No Constant at index %d", index))
}
类、字段、方法、接口存引用
字符串 存常量池索引
引用类
// 符号引用基类
type SymRef struct {
cp *ConstantPool // 符号引用所在的常量池
className string // 类的全限定名
class *Class // 符号引用所属的类
}
func (self *SymRef) ResolvedClass() *Class {
if self.class == nil {
self.resolveClassRef()
}
return self.class
}
func (self *SymRef) resolveClassRef() {
d := self.cp.class
c := d.loader.LoadClass(self.className)
if !c.isAccessibleTo(d) {
panic("java.lang.IllegalAccessError")
}
self.class = c
}
// 类符号引用
type ClassRef struct {
SymRef
}
// 将 classfile.ConstantClassInfo 转化为 ClassRef
func newClassRef(cp *ConstantPool, classInfo *classfile.ConstantClassInfo) *ClassRef {
ref := &ClassRef{}
ref.cp = cp
ref.className = classInfo.Name()
return ref
}
type MemberRef struct {
SymRef
name string
descriptor string
}
func (self *MemberRef) copyMemberRefInfo(refInfo *classfile.ConstantMemberrefInfo) {
self.className = refInfo.ClassName()
self.name, self.descriptor = refInfo.NameAndDescriptor()
}
// getter
func (self *MemberRef) Name() string {
return self.name
}
func (self *MemberRef) Descriptor() string {
return self.descriptor
}