3.2.3 class_def
本节会介绍代表类信息的class_def。图3-6为它的数据结构。
图3-6 class_def数据结构伪代码
图3-6中class_def的几个主要成员变量的解释如下。
·class_idx:指向type_ids,代表本类的类型。
·access_flags:访问标志,比如private、public等。
·superclass_idx:指向type_ids,代表基类类型,如果没有基类则取值为NO_INDEX(值为-1)。
·interfaces_off:如果本类实现了某些接口,则interfaces_off指向文件对应位置,那里存储了一个type_list。该type_list的list数组存储了每一个接口类的type_idx索引(参考图3-5和对应的解释)。
·source_file_idx:指向string_ids,该类对应的源文件名。
·annotations_off:存储和注解有关的信息。
·class_data_off:指向文件对应位置,那里将存储更细节的信息,由class_data_item类型来描述。
·static_values_off:存储用来初始化类的静态变量的值,静态变量如果没有显示设置初值的话,默认是0或者null。如果有初值的话,初值信息就存储在文件static_values_off的地方,对应的数据结构名为encoded_array_item。本章不拟讨论它,读者可自行阅读参考资料[2]。
图3-7 class_data_item及相关数据结构
而一个类的成员变量、成员函数等信息则是通过图3-6中class_data_off域指向一个名为class_data_item结构体来描述的。图3-7为与class_data_item相关的数据结构。
图3-7中最上面为class_data_item的数据结构。其中,static_fields_size、instance_fields_size、direct_methods_size和virtual_methods_size这四个成员变量分别决定了下述数组的长度。
·static_fields:类的静态成员信息,元素类型为encoded_field。
·instance_fields:类的非静态成员信息,元素类型为encoded_field。
·direct_methods:非虚函数信息,元素类型为encoded_method。
·virtual_methods:虚函数信息,元素类型为encoded_method。
而encoded_field和encoded_method用于描述类的成员变量和成员函数的信息。
·encoded_field:field_idx_diff指向field_ids。注意这里是field_idx_diff,它表示除数组里第一个元素的field_idx_diff取值为索引值,该数组后续元素field_idx_diff取值为和前一个索引值的差。access_flags表示成员域的访问标志。
·encoded_method:method_idx_diff指向method_ids。diff的含义与field_idx_diff一样。access_flags表示该函数的访问标志,code_off指向文件对应位置处,那里有一个类型为code_item的结构体,code_item类似于Class文件的Code属性。
注意 这里要特别提醒的是encoded_field和encoded_method中的field_idx_diff以及method_idx_diff域,和之前的xxx_idx不同的是,这里的域名后缀是diff,这代表什么呢?以field_idx_diff为例,为了节省文件空间,field_idx_diff并不直接存储指向field_ids数组的索引,而存储的是encoded_field数组(比如图3-7中的static_fields数组)中当前元素的真正索引值和上一个元素真正索引值的差。那么,第一个元素的field_idx_diff又是和哪个元素相减得到的呢?答案很简单,encoded_field数组第一个元素的field_idx_diff直接存储了索引值。
表3-1展示了access_flags的部分取值情况。
表3-1 access_flags取值情况说明