用go编写java虚拟机(三)class文件读取到内存

一、概要

上篇我们定义了class文件的结构体,这节我们主要实现把class文件读取到内存,注意我们的目的很简单,就是读取字节流解析class文。不会现在处理一些过多的内容。

在class.go文件定义ClassBytes结构体

type ClassBytes struct {
   
   
	Bytes []byte
	Class *Class
}

Bytes是当前读取class文件的字节,Class是需要解析的Class结构体的指针。

二、调整结构体

上节我们定义的结构体做一些简单调整

type Class struct {
   
   
	Magic             uint32             `json:"magic"`               // 魔数
	MinorVersionMin   uint16             `json:"minor_version_min"`   //    副版本号
	MinorVersion      uint16             `json:"minor_version"`       //主版本号
	ConstantPoolCount uint16             `json:"constant_pool_count"` //常量池计数器
	ConstantPoolInfo  []ConstantPoolInfo `json:"constant_pool_info"`  // 常量池
	AccessFlags       uint16             `json:"access_flags"`        //访问标志
	ThisClass         uint16             `json:"this_class"`          //类索引,
	SuperClass        uint16             `json:"super_class"`         //父类索引,
	InterfaceCount    uint16             `json:"interface_count"`     //接口计数器
	interfaces        []interface{
   
   }      `json:"interfaces"`          //接口表
	FieldsCount       uint16             `json:"fields_count"`        //字段计数器
	FieldInfo         []interface{
   
   }      `json:"field_info"`          //字段表
	MethodCount       uint16             `json:"method_count"`        //方法计数器
	MethodInfo        []*Method          `json:"method_info"`         //方法表
	AttributesCount   uint16             `json:"attributes_count"`    //属性计数器
	AttributeInfo     []Attribute        `json:"attribute_info"`
}

我们把[]interface{} 类型能确定的替换成了具体的类型,并且加入了json标签,用于打印一下class的内容,另外由于篇幅的原因,此处不粘贴其它结构体的代码了,我会在文章结尾添加当天的代码下载地址,也会在本篇绑定资源下载,读者可以自行下载代码查阅,这里只粘贴Class

三、解析class

1、在class.go文件定义 AnalysisClass方法

` 提示:请读者理解go语言的方法和函数的区别,方法有接收者调用的时候需要变量.func()这样子来调用,类比java可以把方法看成是对象方法,函数看成是静态方法

func (C *ClassBytes) AnalysisClass() {
   
   
	class := C.Class
	//解析魔数
	class.Magic = binary.BigEndian.Uint32(C.Bytes[:4])
	//小版本号
	class.MinorVersionMin = binary.BigEndian.Uint16(C.Bytes[4:6])
	//大版本号
	class.MinorVersionMin = binary.BigEndian.Uint16(C.Bytes[6:8])
	//读取常量池

	class.ConstantPoolCount = binary.BigEndian.Uint16(C.Bytes[8:10])
	//去除已经读过的字节
	C.Bytes = C.Bytes[10:]
	if class.ConstantPoolCount != 0 {
   
   
		//调用常量池读取方法
		pool := C.AnalysisClassReadeConstantPool(int(class.ConstantPoolCount))
		class.ConstantPoolInfo = pool
	}

	//访问控制
	class.AccessFlags = binary.BigEndian.Uint16(C.Bytes[:2])
	//类索引
	class.ThisClass = binary.BigEndian.Uint16(C.Bytes[2:4])
	//父类
	class.SuperClass = binary.BigEndian.Uint16(C.Bytes[4:6])
	//接口计数器
	class.InterfaceCount = binary.BigEndian.Uint16(C.Bytes[6:8])
	//先去除读过的字节
	C.Bytes = C.Bytes[8:]
	//判断是否用接口
	if class.InterfaceCount != 0 {
   
   
		//解析接口
	}
	//字段计数器
	class.FieldsCount = binary.BigEndian.Uint16(C.Bytes[:2])
	//先去除读过的字节
	C.Bytes = C.Bytes[2:]
	//判断是否有字段
	if class.InterfaceCount != 0 {
   
   
		//解析字段
	}
	//方法计数器
	class.MethodCount = binary.BigEndian.Uint16(C.Bytes[:2])
	//先去除读过的字节
	C.Bytes = C.Bytes[2:]
	//判断是否有方法
	if class.MethodCount != 0 {
   
   
		//解析方法
		method := C.AnalysisClassReadeMethod(int(class.MethodCount))
		class.MethodInfo = method
	}
	//属性计数器
	class.AttributesCount = binary.BigEndian.Uint16(C.Bytes[:2])
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wangkai031

您的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值