美文网首页
10、类加载器

10、类加载器

作者: 陈桐Caliburn | 来源:发表于2020-05-05 11:25 被阅读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

知识扩展

1、依赖classpath 读取class文件
2、map存储class类
3、动态加载class

1、定义classloader

type ClassLoader struct {
    cp       *classpath.Classpath // 用于搜索和读取 class 文件
    classMap map[string]*Class    // 已经加载的类数据,key=全限定类名
}

// 创建一个类加载器
func NewClassLoader(cp *classpath.Classpath) *ClassLoader {
    return &ClassLoader{
        cp:       cp,
        classMap: make(map[string]*Class),
    }
}

// 把类数据加载到方法区
func (self *ClassLoader) LoadClass(name string) *Class {
    if class, ok := self.classMap[name]; ok {
        return class // 类已经加载
    }
    return self.loadNonArrayClass(name) // 普通类的数据来自于class文件,数组类的数据是jvm在运行期间动态生成的
}

2、类加载过程

// 类加载过程
func (self *ClassLoader) loadNonArrayClass(name string) *Class {
    data, entry := self.readClass(name) // 1. 找到class文件并读取为 byte[]
    class := self.defineClass(data)     // 2. byte[] -> ClassFile -> Class,并放入方法区
    link(class)                         // 3. 进行链接
    fmt.Printf("[Loaded %s from %s]\n", name, entry)
    return class
}

readClass 从classpath 读取 class []byte

func (self *ClassLoader) readClass(name string) ([]byte, classpath.Entry) {
    data, entry, err := self.cp.ReadClass(name)
    if err != nil {
        panic("java.lang.ClassNotFoundException: " + name)
    }
    return data, entry
}

defineClass 加载class

func (self *ClassLoader) defineClass(data []byte) *Class {
    class := parseClass(data)
    class.loader = self
    resolveSuperClass(class)          // 递归加载父类
    resolveInterfaces(class)          // 递归加载接口类
    self.classMap[class.name] = class // 放入已加载列表
    return class
}

// byte[] -> ClassFile -> Class
func parseClass(data []byte) *Class {
    cf, err := classfile.Parse(data)
    if err != nil {
        panic("java.lang.ClassFormatError")
    }
    return newClass(cf)
}

func resolveSuperClass(class *Class) {
    if class.name != "java/lang/Object" {
        class.superClass = class.loader.LoadClass(class.superClassName) // 递归加载父类
    }
}

func resolveInterfaces(class *Class) {
    interfaceCount := len(class.interfaceNames)
    if interfaceCount > 0 {
        class.interfaces = make([]*Class, interfaceCount)
        for i, interfaceName := range class.interfaceNames {
            class.interfaces[i] = class.loader.LoadClass(interfaceName)
        }
    }
}

link 链接class
给class赋初始值

func link(class *Class) {
    verify(class)  // 验证
    prepare(class) // 准备
}

// 准备阶段:给类变量分配空间并给予初始值
func prepare(class *Class) {
    calcInstanceFieldSlotIds(class) // 计算实例变量的个数,并分别标号
    calcStaticFieldSlotIds(class)   // 计算类变量的个数,并分别标号
    allocAndInitStaticVars(class)   // 为类变量分配空间并初始化
}

实战项目地址

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

相关文章

网友评论

      本文标题:10、类加载器

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