Class文件格式

来源:互联网 发布:程序员招聘要求英文 编辑:程序博客网 时间:2024/05/22 03:22

一 总体结构
class文件用C语言的结构体这样表示

ClassFile {    u4 magic;    u2 minor_version;    u2 major_version;    u2 constant_pool_count;    cp_info constant_pool[constant_pool_count-1];    u2 access_flags;    u2 this_class;    u2 super_class;    u2 interfaces_count;    u2 interfaces[interfaces_count];    u2 fields_count;    field_info fields[fields_count];    u2 methods_count;    method_info methods[methods_count];    u2 attributes_count;    attribute_info attributes[attributes_count];}

二 CAFEBABE和版本
所有class文件都以十六进制的咖啡宝宝开头,也就是著名的CAFEBABE,如:
这里写图片描述
其次是版本,如图
这里写图片描述
这个就是版本为50.0(十六进制的32就是十进制的50)
版本列表
JDK版本 编译后的版本号 十六进制表示
JDK1.5 49 0X31
JDK1.6 50 0X32
JDK1.7 51 0X33
JDK1.8 52 0X34
所以这表明编译版本为JDK1.6
三 常量池
接着是常量池大小,例子中大小为7,但是实际上数组长度为7-1=6。因为常量池比较特殊,索引从1开始。那么为什么不从0开始呢?因为有些对常量池的引用,需要用0表示不存在引用。因为索引是U2类型,也就是无符号,所以索引不能为负数。如果用负数,只需要用-1表示索引不存在,那么对于其他的负数,就是一个浪费。
常量池结构体,也就是Cp_info的数组,定义如下:
cp_info {
u1 tag;
u1 info[];
}
c语言的u1数组,实际上就是byte数组。u代表的是无符号,1代表的是1一个字节。其中tag代表了常量池的类型,常见类型如下
Tag 类型
07 代表class的索引,后接u2的索引值
01 代表字符串,后接u2的字符串长度和实际字符串内容
0A 方法引用

分析如下
这里写图片描述
这个长度为6的结构体数组,就是常量池,包含了以下内容
索引 类型 内容
1 类 在常量池内索引为5
2 类 在常量池内索引为6
3 字符串 SourceFile
4 字符串 UserService.java
5 字符串 !cn/uce/javassist/demo/UserService
6 字符串 java/lang/Object
四 访问标识符、此类、父类
常量池完毕之后是访问标识符、此类、父类、实现接口数量、字段数、方法数、属性数组。访问标识符长度为2字节,此类长度为2字节,父类长度为2字节,所以这一段总长度为6字节。访问标识符是使用位运算|合并的,因为位数错开了,所以可以看作是加法运算。因为访问标识符是两个字节,所以需要逐个字节进行分析。
第一字节
十六进制值 十进制值 含义
0X40 64 代表枚举
0X20 32 代表注解
0X10 16 代表由编译生成,源码中不出现
0X04 4 代表抽象
第二字节
十六进制值 十进制值 含义
0X20 32 Super
0X10 16 final
0X01 1 public
此类和父类都是U2类型的常量池索引。索引指向的是类的签名字符串。类的签名使用的是/代替点号,比如java.lang.Object就是java/lang/Object。
五 接口
这里写图片描述
六 字段
在有字段的类里,常量池是比较大的,以一个字段的类为例子。
这里写图片描述
七 方法
方法比较复杂,有代码行数表、本地变量表,还有代码。
这里写图片描述
我解释下2A B7 00 01 B1这行代码的含义
2A,指令名为aload0,代表变量表第一个变量入栈,2B是第二个,2C是第三个,2D是第四个,没有第五个了。
0A,是10,,代表CONSTANT_Methodref,其结构体如下
CONSTANT_Methodref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
}class_index为3,name_and_type_index为15,
3的值是07 00 11,11是十六进制,所以指向索引17 ,而索引17是java/lang/Object.
name_and_type_index为15,指向的是0C 00 06 00 07。
这个结构体定义如下:
CONSTANT_NameAndType_info {
u1 tag;
u2 name_index;
u2 descriptor_index;
}
06 是名称索引,值为
07是描述索引,其值为()V。这是构造器的签名
所以这行代码的含义是
1 把this压入栈
2 调用java/lang/Object的方法
3 return
八 属性
在UserService这个例子中,只有一个属性,就是SourceFile属性。需要注意的是虚拟机是不需要sourcefile属性的,所以这个常量池完全可以缩小一点。

原创粉丝点击