当你用16进制编译器打开一个java文件,你就能够看到相似这个的Java文件的模板。 java
Class 文件是一组以 8 位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在 Class 文件中,中间没有任何分隔符。Java 虚拟机规范规定 Class 文件采用一种相似 C 语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:无符号数和表,咱们以后也主要对这两种类型的数据类型进行解析。程序员
_info
结尾。0xCAFEBABE
,它能够用来肯定这个文件是否为一个能被虚拟机接受的 Class 文件(这经过扩展名来识别文件类型要安全,毕竟扩展名是能够随便修改的)。
后 4 个字节则是当前 Class 文件的版本号,其中第 五、6 个字节是次版本号,第 七、8 个字节是主版本号。安全
从第 9 个字节开始,就是常量池的入口,常量池是 Class 文件中:编码
常量池的开始的两个字节,也就是第 九、10 个字节,放置一个 u2 类型的数据,标识常量池中常量的数量 cpc (constant_pool_count),这个计数值有一个十分特殊的地方,就是它是从 1 开始而不是从 0 开始的,也就是说若是 cpc = 22,那么表明常量池中有 21 项常量,索引值为 1 ~ 21,第 0 项常量被空出来,为了知足后面某些指向常量池的索引值的数据在特定状况下须要表达“不引用任何一个常量池项目”时,将让这个索引值指向 0 便可。spa
常量池中记录的是代码出现过的全部 token(类名,成员变量名等,也是咱们接下来要修改的地方)以及符号引用(方法引用,成员变量引用等),主要包括如下两大类常量:3d
常量池中的每一项常量都经过一个表来存储。目前一共有 14 种常量,不过麻烦的地方就在于,这 14 种常量类型每一种都有本身的结构,咱们在这里只详细介绍两种:CONSTANT_Class_info 和 CONSTANT_Utf8_info。code
CONSTANT_Class_info 的存储结构为:cdn
... [ tag=7 ] [ name_index ] ...
... [ 1位 ] [ 2位 ] ...
复制代码
其中,tag 是标志位,用来区分常量类型的,tag = 7 就表示接下来的这个表是一个 CONSTANT_Class_info,name_index 是一个索引值,指向常量池中的一个 CONSTANT_Utf8_info 类型的常量所在的索引值,CONSTANT_Utf8_info 类型常量通常被用来描述类的全限定名、方法名和字段名。它的存储结构以下:blog
... [ tag=1 ] [ 当前常量的长度 len ] [ 常量的符号引用的字符串值 ] ...
... [ 1位 ] [ 2位 ] [ len位 ] ...
复制代码