类文件结构详解.下
当前类、父类、接口索引集合
u2 this_class;//当前类
u2 super_class;//父类
u2 interfaces_count;//接口数量
u2 interfaces[interfaces_count];//一个类可以实现多个接口
Java 类的继承关系由类索引、父类索引和接口索引集合三项确定。类索引、父类索引和接口索引集合按照顺序排在访问标志之后,
类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名,由于 Java 语言的单继承,所以父类索引只有一个,除了 java.lang.Object
之外,所有的 Java 类都有父类,因此除了 java.lang.Object
外,所有 Java 类的父类索引都不为 0。
接口索引集合用来描述这个类实现了那些接口,这些被实现的接口将按 implements
(如果这个类本身是接口的话则是extends
) 后的接口顺序从左到右排列在接口索引集合中。
字段表集合
u2 fields_count;//字段数量
field_info fields[fields_count];//一个类会可以有个字段
字段表(field info)用于描述接口或类中声明的变量。字段包括类级变量以及实例变量,但不包括在方法内部声明的局部变量。
field info(字段表) 的结构:
- access_flags: 字段的作用域(
public
,private
,protected
修饰符),是实例变量还是类变量(static
修饰符),可否被序列化(transient 修饰符),可变性(final),可见性(volatile 修饰符,是否强制从主内存读写)。 - name_index: 对常量池的引用,表示的字段的名称;
- descriptor_index: 对常量池的引用,表示字段和方法的描述符;
- attributes_count: 一个字段还会拥有一些额外的属性,attributes_count 存放属性的个数;
- attributes[attributes_count]: 存放具体属性具体内容。
上述这些信息中,各个修饰符都是布尔值,要么有某个修饰符,要么没有,很适合使用标志位来表示。而字段叫什么名字、字段被定义为什么数据类型这些都是无法固定的,只能引用常量池中常量来描述。
字段的 access_flag 的取值:
方法表集合
u2 methods_count;//方法数量
method_info methods[methods_count];//一个类可以有个多个方法
methods_count 表示方法的数量,而 method_info 表示方法表。
Class 文件存储格式中对方法的描述与对字段的描述几乎采用了完全一致的方式。方法表的结构如同字段表一样,依次包括了访问标志、名称索引、描述符索引、属性表集合几项。
method_info(方法表的) 结构:
方法表的 access_flag 取值:
注意:因为volatile
修饰符和transient
修饰符不可以修饰方法,所以方法表的访问标志中没有这两个对应的标志,但是增加了synchronized
、native
、abstract
等关键字修饰方法,所以也就多了这些关键字对应的标志。
属性表集合
u2 attributes_count;//此类的属性表中的属性数
attribute_info attributes[attributes_count];//属性表集合
在 Class 文件,字段表,方法表中都可以携带自己的属性表集合,以用于描述某些场景专有的信息。与 Class 文件中其它的数据项目要求的顺序、长度和内容不同,属性表集合的限制稍微宽松一些,不再要求各个属性表具有严格的顺序,并且只要不与已有的属性名重复,任何人实现的编译器都可以向属性表中写 入自己定义的属性信息,Java 虚拟机运行时会忽略掉它不认识的属性。