要深入理解class文件结构,请移步:http://blog.csdn.net/column/details/zhangjg-java-blog.html
package a;
/**
* Created by leaves on 2016/11/8.
*/
public class Test2 {
public static final int mStatic = 1111111111;
public static int mStatic2 = 222222222;
public String minstance = "asdf";
public int anum = 1;
public static void main(String[] args) {
System.out.println("Hello, world");
}
}
我们以下java文件为例,分析class文件的结构下面我们分析下他生成的class文件结构
class文件的数据的基本类型:
类 型 | 描 述 |
1个字节,无符号类型 | |
u2 | 2个字节,无符号类型 |
u4 | 4个字节,无符号类型 |
u8 | 8个字节,无符号类型 |
Class文件结构:
类 型 | 名 称 | 数 量 |
u4 | magic | 1 |
u2 | minor_version | 1 |
u2 | major_version | 1 |
u2 | constant_pool_count | 1 |
cp_info | constant_pool | constant_pool_count-1 |
u2 | access_flags | 1 |
u2 | this_class | 1 |
u2 | super_class | 1 |
u2 | interfaces_count | 1 |
u2 | interfaces | interfaces_count |
u2 | fields_count | 1 |
field_info | fields | fields_count |
u2 | methods_count | 1 |
method_info | methods | methods_count |
u2 | attributes_count | 1 |
attribute_info | attributes | attributes_count |
我们分析下上面的class文件,对应各个字段的值如下
这里分析了前面几个字段,以及开始分析常量池,常量池其他的字段就不一一分析了
常量池中各个数据项通过索引来访问, 有点类似与数组, 只不过常量池中的第一项的索引为1, 而不为0, 如果class文件中的其他地方引用了索引为0的常量池项, 就说明它不引用任何常量池项。class文件中的每一种数据项都有自己的类型, 相同的道理,常量池中的每一种数据项也有自己的类型。 常量池中的数据项的类型如下表:
常量池中数据项类型 | 类型标志 | 类型描述 |
CONSTANT_Utf8 | 1 | UTF-8编码的Unicode字符串 |
CONSTANT_Integer | 3 | int类型字面值 |
CONSTANT_Float | 4 | float类型字面值 |
CONSTANT_Long | 5 | long类型字面值 |
CONSTANT_Double | 6 | double类型字面值 |
CONSTANT_Class | 7 | 对一个类或接口的符号引用 |
CONSTANT_String | 8 | String类型字面值 |
CONSTANT_Fieldref | 9 | 对一个字段的符号引用 |
CONSTANT_Methodref | 10 | 对一个类中声明的方法的符号引用 |
CONSTANT_InterfaceMethodref | 11 | 对一个接口中声明的方法的符号引用 |
CONSTANT_NameAndType | 12 | 对一个字段或方法的部分符号引用 |
每个数据项叫做一个XXX_info项, 比如, 一个常量池中一个CONSTANT_Utf8类型的项, 就是一个CONSTANT_Utf8_info 。除此之外, 每个info项中都有一个标志值(tag), 这个标志值表明了这个常量池中的info项的类型是什么, 从上面的表格中可以看出, 一个CONSTANT_Utf8_info中的tag值为1, 而一个CONSTANT_Fieldref_info中的tag值为9 。
我们分析这里的第一个字段field,field字段结构如下
access_flags(2byte 访问修饰符)
name_index(2byte 存储字段名的常量表在常量池中的索引)
description_index(2byte 存储字段的所属类型的常量表在常量池中的索引)
attribute_count(2byte 属性表的数量)
attribute (属性)
这里前面两个字节是0019表示的是ACC_PUBLIC(0x0001) | ACC_STATIC(0x0008) | ACC_FINAL(0x0010)
name_index值为000c表示的字段名在常量池中的索引,对应的是 const #12 = Asciz mStatic;
description_index 对应的是000d 表示的是 const #13 = Asciz I; 代表是个整型
attribute_count 对应0001表示有一个attribute
这里我们也可以跟源码中对应一下
attribute是由attribute_info组成,attribute_info结构如下
attribute_name_index 这里是000e,对应的是 const #14 = Asciz ConstantValue;
attribute_length 这里是00000002表示长队为2
info对应的是000F表示常量池的索引,对应的是const #15 = int 1111111111;
这里开始分析了常量池的最后几个字段以及class文件中的剩下的结构,基本上就是按照对应的字段的结构来分析,主要都是通过常量池中的索引来表示的
可以参考一下几个网站:
http://blog.csdn.net/newthinker_wei/article/details/8028019
http://zhanjia.iteye.com/blog/1857709
http://blog.csdn.net/kobejayandy/article/details/39620833
然后可以用如下命令打印class文件的内容
javap -verbose Test2