JVM常量池元素
11种常量
编号 | 常量池元素名称 | tag位标识 | 含义 |
---|---|---|---|
1 | CONSTANT_Utf8_info | 1 | utf-8编码的字符串 |
2 | CONSTANT_Integer_info | 3 | 整型字面量 |
3 | CONSTANT_Float_info | 4 | 浮点型字面量 |
4 | CONSTANT_Long_info | 5 | 长整型字面量 |
5 | CONSTANT_Double_info | 6 | 双精度字面量 |
6 | CONSTANT_Class_info | 7 | 类或接口的符号引用 |
7 | CONSTANT_String_info | 8 | 字符串类型字面量 |
8 | CONSTANT_Fieldref_info | 9 | 字段的符号引用 |
9 | CONSTANT_Methodref_info | 10 | 类中方法的符号引用 |
10 | CONSTANT_InterfaceMethodref_info | 11 | 接口中方法的符号引用 |
11 | CONSTANT_NameAndType_info | 12 | 字段和方法的名称以及类型的符号引用 |
常量池元素的复合结构
类型/含义 | 结构 | 类型 | 描述 |
---|---|---|---|
CONSTANT_Utf8_info UTF-8编码的字符串 | tag | u1 | 值为1 |
length | u2 | utf-8缩略编码字符串所占字节数 | |
bytes | u1 | 长度为length的utf-8编码字符串 | |
CONSTANT_Integer_info 整型字面量 | tag | u1 | 值为3 |
bytes | u4 | 按照高位在前存储的int值 | |
CONSTANT_Float_info 浮点型字面量 | tag | u1 | 值为4 |
bytes | u4 | 按照高位在前存储的float值 | |
CONSTANT_Long_info 长整型字面量 | tag | u1 | 值为5 |
bytes | u8 | 按照高位在前存储的long值 | |
CONSTANT_Double_info 双精度浮点型字面量 | tag | u1 | 值为6 |
bytes | u8 | 按照高位在前存储的double值 | |
CONSTANT_Class_info 类或接口的符号引用 | tag | u1 | 值为7 |
index | u2 | 指向全限定名常量项的索引 | |
CONSTANT_String_info 字符串类型字面量 | tag | u1 | 值为8 |
index | u2 | 指向字符串字面量的索引 | |
CONSTANT_Fieldref_info 字段的符号引用 | tag | u1 | 值为9 |
index | u2 | 指向CONSTANT_Class_info的索引 | |
index | u2 | 指向Constant_NameAndType_info的索引 | |
CONSTANT_Methodref_info 类中方法的符号引用 | tag | u1 | 值为10 |
index | u2 | 指向CONSTANT_Class_info的索引 | |
index | u2 | 指向Constant_NameAndType_info的索引 | |
CONSTANT_InterfaceMethodref_info 接口中方法的符号引用 | tag | u1 | 值为11 |
index | u2 | 指向CONSTANT_Class_info的索引 | |
index | u2 | 指向Constant_NameAndType_info的索引 | |
CONSTANT_NameAndType_info 字段和方法的名称以及类型的符号引用 | tag | u1 | 值为12 |
index | u2 | 指向字段或方法名称常量项的索引 | |
index | u2 | 指向字段或方法描述符常量项的索引 |
访问标识与继承信息
字节码文件中,紧跟着常量池信息之后的就是访问标志,access_flags结构,该结构类型是u2,占用2个字节空间。
access_flags标识代表访问标志位,该标志用于标注类或接口层次的访问信息,如当前class是类还是接口,是否是public等。
access_flags可选项
标志名称 | 标识值 | 含义 |
---|---|---|
ACC_PUBLIC | 0x0001 | 是否是public |
ACC_FINAL | 0x0010 | 是否是final,只有类可以设置为这个值 |
ACC_SUPER | 0x0020 | 是否允许使用invokespecial,jdk 1.2后这个值为真 |
ACC_INTERFACE | 0x0200 | 标识这是一个接口 |
ACC_ABSTRACT | 0x0400 | 是否是抽象类型,对于接口和抽象类为真,其他类为假 |
ACC_SYNTHETIC | 0x1000 | 标识这个类不是由用户代码产生 |
ACC_ANNOTATION | 0x2000 | 标识这是一个注解 |
ACC_ENUM | 0x4000 | 标识这是一个枚举 |
public final class类的访问标志值是 0x0031,也就是ACC_PUBLIC,FINAL,SUPER的异或值。
public class类的访问标志值是 0x0021
fields结构组成
类型 | 名称 | 数量 |
---|---|---|
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 |
字段描述符与基本数据类型对应表:
描述符 | 含义 |
---|---|
B | byte |
C | char |
D | double |
F | float |
I | int |
J | long |
S | short |
Z | boolean |
V | 特殊类型void |
L | 对象类型,比如Ljava/lang/Object |
String[][],的描述符为[[Ljava/lang/String;
methods结构组成
类型 | 名称 | 数量 |
---|---|---|
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_SYNCHRONIZED | 0x0020 | 字段是否是synchronized |
ACC_BRIDGE | 0x0040 | 方法是否由编译器产生的桥接方法 |
ACC_VARARGS | 0x0080 | 方法是否接收可变参数 |
ACC_NATIVE | 0x0100 | 方法是否是native |
ACC_ABSTRACT | 0x0400 | 方法是否abstract |
ACC_STRICTFP | 0x0800 | 方法是否strictfp |
ACC_SYNTHETIC | 0x1000 | 方法是否是编译器自动生成 |
9大属性表集合
属性名称 | 使用位置 | 含义 |
---|---|---|
Code | 方法表 | 含有字节码指令 |
ConstantValue | 字段表 | final关键字定义的常量值 |
Deprecated | 类文件,字段表,方法表 | 被声明为deprecated的方法和字段 |
Exceptions | 方法表 | 方法抛出的异常 |
InnerClassed | 类文件 | 内部类列表 |
LineNumberTable | Code属性 | 源码行号与字节码指令的对应关系 |
LocalVariableTable | Code属性 | 方法局部变量的描述 |
SourceFile | 类文件 | 源文件名称 |
Synthetic | 类文件、字段表、方法表 | 方法或字段是否是编译器自动生成 |
Code属性(除了接口方法和抽象方法以外,都有)
类型 | 名称 | 数量 |
---|---|---|
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | max_stack | 1 |
u2 | max_locals | 1 |
u4 | code_length | 1 |
u1 | code | code_length |
u2 | exception_table_length | 1 |
exception_info | exception_table | exception_table_length |
u2 | atribute_count | 1 |
attribute_info | attributes | atribute_count |
code_length长度为u4,所以如果一个方法超过了65535条字节码指令,javac将拒绝编译。
ConstantValue属性
类型 | 名称 | 数量 |
---|---|---|
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | constantvalue_index | 1 |
虚拟机规范要求,只有static修饰的字段才能有constantValue属性,但是编译器又加了个条件,必须同时被final和static修饰的字段才能有这个属性。
否则在< clinit>中初始化。
Exceptions属性
方法描述时throws关键字抛出的异常,与Code属性平级。
类型 | 名称 | 数量 |
---|---|---|
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | number_of_exceptions | 1 |
u2 | exception_index_table | number_of_exceptions |
InnerClass属性
类型 | 名称 | 数量 |
---|---|---|
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | numbers_of_classes | 1 |
inner_classes_info | inner_classed | numbers_of_classes |
inner_classes_info表结构
类型 | 名称 | 数量 |
---|---|---|
u2 | inner_classes_info_index | 1 |
u2 | outer_classes_info_index | 1 |
u2 | inner_name_index | 1 |
u2 | inner_name_access_flags | 1 |
lineNumberTable
类型 | 名称 | 数量 |
---|---|---|
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | line_number_table_length | 1 |
line_number_info | line_number_table | line_number_table_length |
line_number_info
类型 | 名称 | 数量 | 说明 |
---|---|---|---|
u2 | start_pc | 1 | 字节码行号 |
u2 | line | 1 | java源码行号 |
localvariabletable属性
用于描述栈帧中局部变量表中的变量与Java源码中定义的变量之间的关系
类型 | 名称 | 数量 |
---|---|---|
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | local_variable_table_length | 1 |
local_variable_info | local_variable_table | local_variable_table_length |
local_variable_info的结构
类型 | 名称 | 数量 | 说明 |
---|---|---|---|
u2 | start_pc | 1 | 局部变量的声明周期开始的字节码偏移量 |
u2 | length | 1 | 局部变量作用范围覆盖的长度 |
u2 | name_index | 1 | 变量名索引 |
u2 | description_index | 1 | 局部变量描述符索引 |
u2 | index | 1 | 局部变量在栈帧局部变量表中slot的位置 |
不生成该属性,则他人引用这个方法时,参数名称都将丢失,调试时调试器无法根据参数名称从运行上下文中获取参数值。
SourceFile属性
类型 | 名称 | 数量 |
---|---|---|
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
u2 | sourcefile_index | 1 |
Deprecated和synthetic没有属性值,只存在有和没有的区别。
类型 | 名称 | 数量 |
---|---|---|
u2 | attribute_name_index | 1 |
u4 | attribute_length | 1 |
attribute_length的值必须为0x0000 0000