|
|
|
@ -6,6 +6,8 @@ |
|
|
|
|
|
|
|
|
|
1. 常量项的类型和关系 |
|
|
|
|
2. 信息描述规则 |
|
|
|
|
3. field_info 和 method_info |
|
|
|
|
4. access_flags 介绍 |
|
|
|
|
|
|
|
|
|
#### 常量项的类型和关系 |
|
|
|
|
|
|
|
|
@ -134,4 +136,104 @@ CONSTANT_Float_info{ |
|
|
|
|
|
|
|
|
|
#### 信息描述规则 |
|
|
|
|
|
|
|
|
|
根据 Java 虚拟机规范,如何用字符串来描述成员变量、成员函数是有讲究的, |
|
|
|
|
根据 Java 虚拟机规范,如何用字符串来描述成员变量、成员函数是有讲究的,这些规则主要集中在数据类型、成员变量和成员函数的描述规则。包括 |
|
|
|
|
|
|
|
|
|
- 数据类型的描述规则 |
|
|
|
|
- 成员变量的描述规则,即 Field Descriptor |
|
|
|
|
- 成员函数的描述规则,即 Method Descriptor |
|
|
|
|
|
|
|
|
|
##### 数据类型的描述规则 |
|
|
|
|
|
|
|
|
|
| 类型 | 描述 | |
|
|
|
|
| ------- | ------------------ | |
|
|
|
|
| byte | B | |
|
|
|
|
| char | C | |
|
|
|
|
| double | D | |
|
|
|
|
| float | F | |
|
|
|
|
| int | I | |
|
|
|
|
| long | J | |
|
|
|
|
| short | S | |
|
|
|
|
| boolean | B | |
|
|
|
|
| String | Ljava/lang/String; | |
|
|
|
|
| int[] | [I | |
|
|
|
|
|
|
|
|
|
##### 成员变量描述规则 |
|
|
|
|
|
|
|
|
|
就是类似上面的数据类型。 |
|
|
|
|
|
|
|
|
|
##### 成员函数描述规则 |
|
|
|
|
|
|
|
|
|
和成员变量略有不同的是,一个成员函数(Method Description)的描述需要包含返回值及参数的数据类型。 |
|
|
|
|
|
|
|
|
|
比如,对于 System.out.print(String str) 函数,它的 Method Description 是: |
|
|
|
|
|
|
|
|
|
```java |
|
|
|
|
(Ljava/lang/String;)V |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
Method Description 不包含函数名,这样做的目的其实也是为了节省空间,因为很多函数可能名字不同,但是它们的 Method Description 是一样的。 |
|
|
|
|
|
|
|
|
|
#### field_info 和 method_info |
|
|
|
|
|
|
|
|
|
它们的数据结构伪代码如下: |
|
|
|
|
|
|
|
|
|
```java |
|
|
|
|
field_info{ |
|
|
|
|
u2 access_flags; |
|
|
|
|
u2 name_index; |
|
|
|
|
u2 descriptor_index; |
|
|
|
|
u2 attributes_count; |
|
|
|
|
attribute_info attributes[attributes_count]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
method_info{ |
|
|
|
|
u2 access_flags; |
|
|
|
|
u2 name_index; |
|
|
|
|
u2 descriptor_index; |
|
|
|
|
u2 attributes_count; |
|
|
|
|
attribute_info attributes[attributes_count]; |
|
|
|
|
} |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
- access_flags |
|
|
|
|
|
|
|
|
|
访问标志 |
|
|
|
|
|
|
|
|
|
- name_index |
|
|
|
|
|
|
|
|
|
指向成员变量或成员函数的名字的 Utf8_info 常量项。 |
|
|
|
|
|
|
|
|
|
- descriptor_index |
|
|
|
|
|
|
|
|
|
也指向 Utf8_info 常量项,其内容分别是描述成员变量的 FieldDescriptor 和描述成员函数的 MethodDescriptor。 |
|
|
|
|
|
|
|
|
|
- attributes |
|
|
|
|
|
|
|
|
|
为属性信息,成员域和成员函数都包含若干属性。 |
|
|
|
|
|
|
|
|
|
既然 method_info 描述的是一个成员函数,那么这个函数对应的代码经过编译后得到的 Java 字节码存储在什么地方呢? |
|
|
|
|
|
|
|
|
|
其实存储在属性中。 |
|
|
|
|
|
|
|
|
|
#### access_flags |
|
|
|
|
|
|
|
|
|
access_flags 其实就是访问修饰符,如下: |
|
|
|
|
|
|
|
|
|
| 标识位 | 说明 | |
|
|
|
|
| ---------------- | -------------------- | |
|
|
|
|
| ACC_PUBLIC | public | |
|
|
|
|
| ACC_FINAL | final | |
|
|
|
|
| ACC_INTERFACE | interface | |
|
|
|
|
| ACC_ABSTRACT | abstract | |
|
|
|
|
| ACC_ANNOTATION | annotation | |
|
|
|
|
| ACC_ENUM | 枚举类型 | |
|
|
|
|
| ACC_PROTECT | protect | |
|
|
|
|
| ACC_STATIC | static | |
|
|
|
|
| ACC_VOLATILE | volatile | |
|
|
|
|
| ACC_TRANSIENT | transient | |
|
|
|
|
| ACC_NATIVE | native | |
|
|
|
|
| ACC_VARARGS | 可变长参数个数的函数 | |
|
|
|
|
| ACC_SYNCHRONIZED | synchronized | |
|
|
|
|
| ... | ... | |
|
|
|
|
|
|
|
|
|
之前写过,关于 synchronized 方法的实现原理,是在方法前面加上 ACC_SYNCHRONIZED 的标识位,原本我以为只有 synchronized 方法会有这种标识位,其他一些访问修饰符都没有,看来还是 too young too simple~ |