正确解析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.

本文详述了如何使用Golang解析Java的class文件,包括理解数据类型、处理字节序问题,以及介绍Go读取二进制数据的常用函数。文章详细剖析了class文件的结构,如常量池、访问标记、接口、字段和方法等,强调了在解析过程中不必完全实现所有数据类型,只需关注实际需要的部分。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



