[Golang实现JVM第二篇]解析class文件是万里长征第一步

正确解析class文件是万里长征第一步。本篇我们会全程使用golang完成class文件的解析工作。

数据类型

JVM的class文件完全是二进制文件,最小单位是字节,也有数据类型,但都是字节的整数倍(废话)。规范中class文件一共有两类数据,一种是无符号整数,一种是表。无符号整数一共有u1,u2, u4, u8四种类型,分别表示8bit, 16bit, 32bit, 64bit的无符号整数。表则是无符号整数的集合,class文件中在出现表之前都会先跟着一个u2类型的长度数据,表名后面表的总长度,这样才能正确解析表。

另外还要注意字节序的问题,JVM规范规定class文件统一采用Big Endian字节序,也就是低地址存储高位,高地址存放低位。如果是用C/C++语言写JVM,则程序使用的字节序是跟CPU绑定的,比如intel的x86平台使用Little Endian,PowerPC则是Big Endian。不过幸好我们的主角是Go, Go统一采用大端,这样就不需要操心平台了。假设我们用一个二元素的[]byte数组来存储从class文件中按顺序读到的u16类型数据,那么byte[0]就是u16的高8位,byte[1]就是低8位,组合起来就是:

uint16(b[1]) | uint16(b[0]) << 8

即将高位左移8位,然后跟低位做按位或操作即可还原。

Go读取二进制数据常用函数

我们使用标准库的io.Reader接口从文件中读取字节,然后从字节数组中还原原本的数据类型,例如读取u16类型的数据可以这么写:

func ReadInt16(bufReader io.Reader) (uint16, error) {
   
	numBuf := make([]byte, 2, 2)
	_, err := bufReader.Read(numBuf)
	if nil != err {
   
		return 0, err
	}

	var num uint16
	err = binary.Read(bytes
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值