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) // 为类变量分配空间并初始化
}
网友评论