类文件结构-字段表集合、方法表集合
字段表集合
字段表用于描述接口或类中声明的变量。字段包括类级变量以及实例级变量,但不包括在方法内部声明的局部变量。
字段表的结构如下表:
| 名称 | 类型 | 数量 |
|---|---|---|
| u2 | access_flags | 1 |
| u2 | name_index | 1 |
| u2 | descriptor_index | 1 |
| u2 | attributes_count | 1 |
| attribute_info | attributes | attributes_count |
access_flags可以设置的标志位和含义如下表:
| 标志名称 | 标志值 | 含义 |
|---|---|---|
| ACC_PUBLIC | 0x0001 | 字段是否public |
| ACC_PRIVATE | 0x0002 | 字段是否private |
| ACC_PROTECTED | 0x0004 | 字段是否protected |
| ACC_STATIC | 0x0008 | 字段是否static |
| ACC_FINAL | 0x0010 | 字段是否final |
| ACC_VOLATILE | 0x0040 | 字段是否volatile |
| ACC_TRANSIENT | 0x0080 | 字段是否transient |
| ACC_SYNTHETIC | 0x1000 | 字段是否由编译器自动产生的 |
| ACC_ENUM | 0x4000 | 字段是否enum |
name_index和descriptor_index是对常量池的引用,分别代表着字段简单名称和方法的描述符。
描述符含义如下表:
| 标识字符 | 含义 |
|---|---|
| B | 基本类型byte |
| C | 基本类型char |
| D | 基本类型double |
| F | 基本类型float |
| I | 基本类型int |
| J | 基本类型long |
| S | 基本类型short |
| Z | 基本类型boolean |
| V | 特殊类型void |
| L | 对象类型,如Ljava/lang/Object |
对于数组类型,每一维度将使用一个前置的“[”字符来描述,如“[[Ljava/lang/String”记录了一个String[][],“[I”记录了一个int[]。
用描述符来描述方法时,按照先参数列表,后返回值的顺序描述,参数列表按照参数的严格顺序放在一组小括号之内。如void inc()的描述符是"()V",int indexOf(char[] source,int sourceOffset, int sourceCount, char[] target, int targetOffset, int targetCount, int fromIndex)的描述符为“([CII[CIII)I”。
最后是属性表集合用于存放一些额外的信息。
方法表集合
方法表的结构几乎和字段表一样
| 名称 | 类型 | 数量 |
|---|---|---|
| u2 | access_flags | 1 |
| u2 | name_index | 1 |
| u2 | descriptor_index | 1 |
| u2 | attributes_count | 1 |
| attribute_info | attributes | attributes_count |
方法访问标志见下表:
| 标志名称 | 标志值 | 含义 |
|---|---|---|
| ACC_PUBLIC | 0x0001 | 方法是否public |
| ACC_PRIVATE | 0x0002 | 方法是否private |
| ACC_PROTECTED | 0x0004 | 方法是否protected |
| ACC_STATIC | 0x0008 | 方法是否static |
| ACC_FINAL | 0x0010 | 方法是否final |
| ACC_SYNCHRONIZED | 0x0020 | 方法是否synchronized |
| ACC_BRIDGE | 0x0040 | 方法是否是由编译器产生的桥接方法 |
| ACC_VARARGS | 0x0080 | 方法是否接受不定参数 |
| ACC_NATIVE | 0x0100 | 方法是否native |
| ACC_ABSTRACT | 0x0400 | 方法是否abstract |
| ACC_STRICTFP | 0x0800 | 方法是否strictfp |
| ACC_SYNTHETIC | 0x1000 | 方法是否由编译器自动产生的 |
方法里的Java代码经过编译器编译成字节码指令后,存放在方法属性表集合中一个名为Code的属性里面。