https://gitee.com/vectorx/NOTE_JVM
https://codechina.csdn.net/qq_35925558/NOTE_JVM
https://github.com/uxiahnan/NOTE_JVM
目录
Class文件结构
1. Class字节码文件结构
|
类型 |
名称 |
说明 |
长度 |
数量 |
魔数 |
u4 |
magic |
魔数,识别Class文件格式 |
4个字节 |
1 |
版本号 |
u2 |
minor_version |
副版本号(小版本) |
2个字节 |
1 |
u2 |
major_version |
主版本号(大版本) |
2个字节 |
1 |
常量池集合 |
u2 |
constant_pool_count |
常量池计数器 |
2个字节 |
1 |
cp_info |
constant_pool |
常量池表 |
n个字节 |
constant_pool_count - 1 |
访问标识 |
u2 |
access_flags |
访问标识 |
2个字节 |
1 |
索引集合 |
u2 |
this_class |
类索引 |
2个字节 |
1 |
u2 |
super_class |
父类索引 |
2个字节 |
1 |
u2 |
interfaces_count |
接口计数器 |
2个字节 |
1 |
u2 |
interfaces |
接口索引集合 |
2个字节 |
interfaces_count |
字段表集合 |
u2 |
fields_count |
字段计数器 |
2个字节 |
1 |
field_info |
fields |
字段表 |
n个字节 |
fields_count |
方法表集合 |
u2 |
methods_count |
方法计数器 |
2个字节 |
1 |
method_info |
methods |
方法表 |
n个字节 |
methods_count |
属性表集合 |
u2 |
attributes_count |
属性计数器 |
2个字节 |
1 |
attribute_info |
attributes |
属性表 |
n个字节 |
attributes_count |
2. Class文件数据类型
数据类型 |
定义 |
说明 |
无符号数 |
无符号数可以用来描述数字、索引引用、数量值或按照utf-8编码构成的字符串值。 |
其中无符号数属于基本的数据类型。 以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节 |
表 |
表是由多个无符号数或其他表构成的复合数据结构。 |
所有的表都以“_info”结尾。 由于表没有固定长度,所以通常会在其前面加上个数说明。 |
3. 魔数
4. 文件版本号
4.1. Class文件版本号对应关系
主版本(十进制) |
副版本(十进制) |
编译器版本 |
45 |
3 |
1.1 |
46 |
0 |
1.2 |
47 |
0 |
1.3 |
48 |
0 |
1.4 |
49 |
0 |
1.5 |
50 |
0 |
1.6 |
51 |
0 |
1.7 |
52 |
0 |
1.8 |
53 |
0 |
1.9 |
54 |
0 |
1.10 |
55 |
0 |
1.11 |
5. 常量池集合
类型 |
名称 |
数量 |
u2(无符号数) |
constant_pool_count |
1 |
cp_info(表) |
constant_pool |
constant_pool_count - 1 |
5.1. 常量池计数器
5.2. 常量池表
类型 |
标志(或标识) |
描述 |
CONSTANT_Utf8_info |
1 |
UTF-8编码的字符串 |
CONSTANT_Integer_info |
3 |
整型字面量 |
CONSTANT_Float_info |
4 |
浮点型字面量 |
CONSTANT_Long_info |
5 |
长整型字面量 |
CONSTANT_Double_info |
6 |
双精度浮点型字面量 |
CONSTANT_Class_info |
7 |
类或接口的符号引用 |
CONSTANT_String_info |
8 |
字符串类型字面量 |
CONSTANT_Fieldref_info |
9 |
字段的符号引用 |
CONSTANT_Methodref_info |
10 |
类中方法的符号引用 |
CONSTANT_InterfaceMethodref_info |
11 |
接口中方法的符号引用 |
CONSTANT_NameAndType_info |
12 |
字段或方法的符号引用 |
CONSTANT_MethodHandle_info |
15 |
表示方法句柄 |
CONSTANT_MethodType_info |
16 |
标志方法类型 |
CONSTANT_InvokeDynamic_info |
18 |
表示一个动态方法调用点 |
标志符 |
含义 |
B |
基本数据类型byte |
C |
基本数据类型char |
D |
基本数据类型double |
F |
基本数据类型float |
I |
基本数据类型int |
J |
基本数据类型long |
S |
基本数据类型short |
Z |
基本数据类型boolean |
V |
代表void类型 |
L |
对象类型,比如:Ljava/lang/Object;
|
[ |
数组类型,代表一维数组。比如:`double[][][] is [[[D |
6. 访问标志
标志名称 |
标志值 |
含义 |
ACC_PUBLIC |
0x0001 |
标志为public类型 |
ACC_FINAL |
0x0010 |
标志被声明为final,只有类可以设置 |
ACC_SUPER |
0x0020 |
标志允许使用invokespecial字节码指令的新语义,JDK1.0.2之后编译出来的类的这个标志默认为真。(使用增强的方法调用父类方法) |
ACC_INTERFACE |
0x0200 |
标志这是一个接口 |
ACC_ABSTRACT |
0x0400 |
是否为abstract类型,对于接口或者抽象类来说,次标志值为真,其他类型为假 |
ACC_SYNTHETIC |
0x1000 |
标志此类并非由用户代码产生(即:由编译器产生的类,没有源码对应) |
ACC_ANNOTATION |
0x2000 |
标志这是一个注解 |
ACC_ENUM |
0x4000 |
标志这是一个枚举 |
7. 类索引、父类索引、接口索引
长度 |
含义 |
u2 |
this_class |
u2 |
super_class |
u2 |
interfaces_count |
u2 |
interfaces[interfaces_count] |
8. 字段表集合
8.1. 字段计数器
标志名称 |
标志值 |
含义 |
数量 |
u2 |
access_flags |
访问标志 |
1 |
u2 |
name_index |
字段名索引 |
1 |
u2 |
descriptor_index |
描述符索引 |
1 |
u2 |
attributes_count |
属性计数器 |
1 |
attribute_info |
attributes |
属性集合 |
attributes_count |
8.2. 字段表
标志名称 |
标志值 |
含义 |
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_TRANSTENT |
0x0080 |
字段是否为transient |
ACC_SYNCHETIC |
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;
|
[ |
数组类型,代表一维数组。比如:`double[][][] is [[[D |
9. 方法表集合
9.1. 方法计数器
9.2. 方法表
标志名称 |
标志值 |
含义 |
数量 |
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,静态方法 |
10. 属性表集合
10.1. 属性计数器
10.2. 属性表
类型 |
名称 |
数量 |
含义 |
u2 |
attribute_name_index |
1 |
属性名索引 |
u4 |
attribute_length |
1 |
属性长度 |
u1 |
info |
attribute_length |
属性表 |
属性名称 |
使用位置 |
含义 |
Code |
方法表 |
Java代码编译成的字节码指令 |
ConstantValue |
字段表 |
final关键字定义的常量池 |
Deprecated |
类,方法,字段表 |
被声明为deprecated的方法和字段 |
Exceptions |
方法表 |
方法抛出的异常 |
EnclosingMethod |
类文件 |
仅当一个类为局部类或者匿名类时才能拥有这个属性,这个属性用于标识这个类所在的外围方法 |
InnerClass |
类文件 |
内部类列表 |
LineNumberTable |
Code属性 |
Java源码的行号与字节码指令的对应关系 |
LocalVariableTable |
Code属性 |
方法的局部变量描述 |
StackMapTable |
Code属性 |
JDK1.6中新增的属性,供新的类型检查检验器和处理目标方法的局部变量和操作数有所需要的类是否匹配 |
Signature |
类,方法表,字段表 |
用于支持泛型情况下的方法签名 |
SourceFile |
类文件 |
记录源文件名称 |
SourceDebugExtension |
类文件 |
用于存储额外的调试信息 |
Synthetic |
类,方法表,字段表 |
标志方法或字段为编译器自动生成的 |
LocalVariableTypeTable |
类 |
是哟很难过特征签名代替描述符,是为了引入泛型语法之后能描述泛型参数化类型而添加 |
RuntimeVisibleAnnotations |
类,方法表,字段表 |
为动态注解提供支持 |
RuntimeInvisibleAnnotations |
类,方法表,字段表 |
用于指明哪些注解是运行时不可见的 |
RuntimeVisibleParameterAnnotation |
方法表 |
作用与RuntimeVisibleAnnotations属性类似,只不过作用对象或方法 |
RuntimeInvisibleParameterAnnotation |
方法表 |
作用与RuntimeInvisibleAnnotations属性类似,只不过作用对象或方法 |
AnnotationDefault |
方法表 |
用于记录注解类元素的默认值 |
BootstrapMethods |
类文件 |
用于保存invokeddynamic指令引用的引导方法限定符 |
类型 |
名称 |
数量 |
含义 |
u2 |
attribute_name_index |
1 |
属性名索引 |
u4 |
attribute_length |
1 |
属性长度 |
u2 |
max_stack |
1 |
操作数栈深度的最大值 |
u2 |
max_locals |
1 |
局部变量表所需的存续空间 |
u4 |
code_length |
1 |
字节码指令的长度 |
u1 |
code |
code_lenth |
存储字节码指令 |
u2 |
exception_table_length |
1 |
异常表长度 |
exception_info |
exception_table |
exception_length |
异常表 |
u2 |
attributes_count |
1 |
属性集合计数器 |
attribute_info |
attributes |
attributes_count |
属性集合 |
下一篇 <JVM中篇:字节码与类的加载篇>02-字节码指令集