准备
class文件是Java虚拟机唯一可以识别的文件,根据Class文件我们可以完成一个程序的运行,本节文章是本人解析一个基本Class文件的全过程,记录在此,希望能提供给正在前进路上的同学作为辅助作用,下面是我们要解析Class文件必要条件。
代码
以下是一个简单的Java类,一个私有变量,一个公开方法。
public class TestClass {
private int a;
public int increment() {
return a + 1;
}
}
将这个类编译为Class文件
准备文本编辑器
本人使用Sublime Text打开我们编译后的Class文件,主要目的是对照《Java虚拟机规范》中的Class文件的数据结构,下面是Sublime Text下载的网址。
Sublime Text
使用Sumlime打开Clas文件
《Java虚拟机规范》
我们需要按照Java虚拟机规范中的数据结构,进行Class文件的十六进制码进行解析,所以这里需要按照官网,进行解析,以下是PDF在线链接,本节使用Java8版本。
Java虚拟机规范1.8
打开《Java虚拟机规范》
解析
我们需要知道一个Class文件由哪些数据结构组成,并排列出来,一项数据占几个字节,这些我们都要知道。
我们首先需要记录,这个Class文件的大体结构,Class文件的数据结构及顺序都是需要严格按照《Java虚拟机规范》生成的,找到《Java虚拟机规范》中的 “The Class File Format (Class文件格式)”中的Class结构项。
需要解释的是,这个ClassFile数据结构中的U2、u4分别代表两个字节、四个字节,其对应的右边的英文项,代表着其数据的常量项,Class文件是一定按照这个结构进行构件的,《Java虚拟机规范》中也说明了每一项的描述,本人结合官网整理如下:
这个是本人整理的Class文件的数据结构,有且只有这16项,具体的每一项,本文稍后都有解释。其实Class文件并不复杂,只是Class中的引用比较多,例如constant_pool_info中,这是一个常量池,池中记录着类、方法、字面量等描述符,是相互引用的方式。
javap查看class文件具体结构
使用javap查看文件结构,主要是为了供我们于Class二进制方式进行比对时的一个参照物,以说明我们解读class文件时得出的结论是正确的。其余我们需要确定我们常量池中的顺序以及所对应的常量池名。
javap -v TestClass.class
输出结果
根据javap所输出的数据结构,我们得到了大致的数据结构,剩下的我们需要自行解析,并比对class中的十六进制数进行填写。这里采用yaml文本格式进行填充,yaml格式能很直观的展现出一个对象的数据结构,并且采用这种方式也可以很直接的将解析的值带入。针对我们要解析的class文件,其中____是我们要填充的数据,并且也进行了简单的注释说明字段的含义及所占用的字节。结构如下:
class:
#魔数 u4
magic-number: ____
#小版本号 u2
minor-version: ____
#大版本号 u2
major-version: ____
#常量池
constant-pool:
#常量池总数 u2
count: ____
#常量池(数组)
constants: ____
#访问标志 u2
access_flags: ____
#当前类 u2
this_class: ____
#父类 u2
super_class: ____
#接口
interface:
# u2
count: ____
interfaces:
#字段
field:
# u2
count: ____
fields: ____
#方法
method:
# u2
count: ____
methods: ____
#属性
attributes:
#u2
count: ____
attributes: ____
有了大致的结构,我们就可以开始解析之路啦!!
魔数
魔数项提供标识类文件格式的魔术数;它的值为0xCAFEBABE,这个值是固定的,每个文件都有属于自己的魔数,但在class文件中,CAFEBABE就是class文件的魔数,它占用4个字节。
随后将CAFEBABE填入我们的yaml文件中:
小版本号
小版本号占用2个字节,因此,将class文件中的0000转换为十进制为0,所以小版本号为0;
大版本号
。。。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net