JVM只和Class文件这种特定的二进制文件格式所关联。
Class文件包含了JVM指令集和符号表、若干其他辅助信息。
Class长度为8位二进制。
0.class字节码文件结构
class文件 |
---|
文件头部 |
常量池区域 |
当前类的一些描述信息 |
字段表集合 |
方法表集合 |
属性表集合 |
1.文件头部
名称 | 类型 | 说明 |
---|---|---|
magic(固定0xCA0xFE0xBA0xBE) | u4 | 魔数,确定此文件是否为class文件,class文件魔数为(cafebabe) |
minor_version | u2 | 次版本信息 |
major_version | u2 | 主版本信息 |
2.常量池区域
常量池可以理解为Class文件之中的资源仓库,主要存储字面量和符号引用。
名称 | 类型 | 说明 |
---|---|---|
constant_pool_count | u2 | 常量池容量计数值;由于常量池中常量的数量是不固定的,所以在常量池的入口需要放置(并且下标从1开始到21)不从0开始的原因:在于满足后面某些指向常量池的索引值的数据在特定情况下需要表达“不引用任何一个常量池项目”的含义 |
constant_pool[constant_pool_count-1]u2 | cp_info | - |
|
|
类型 | 标志 | 描述 |
---|---|---|
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 | 表示一个动态方法调用点 |
常量池结构
3.当前类的一些描述信息
名称 | 类型 | 说明 |
---|---|---|
access_flags | u2 | 访问标识 |
this_class | u2 | 当前类信息 |
super_class | u2 | 父类信息只有Object类没有该信息 |
interfaces_count | u2 | 接口数 |
interfaces[interfaces_count] | u2 | 接口信息 |
访问标识 | 标志值 | 含义 |
---|---|---|
ACC_PUBLIC | 0x0001 | |
ACC_FINAL | 0x0010 | |
ACC_SUPER | 0x0020 | 是否允许使用invokespecial字节码指令 |
ACC_INTERFACE | 0x0200 | |
ACC_ABSTRACT | 0x0400 | abstract类,接口和抽象类此值为真,其他类值为假 |
ACC_SYNTHETIC | 0x1000 | 标志这个类并非由用户代码产生的 |
ACC_ANNOTATION | 0x2000 | |
ACC_ENUM | 0x4000 | - |
4.字段表集合
名称 | 类型 | 说明 |
---|---|---|
fields_count | u2 | 字段数量 |
fields[fields_count] | field_info | 字段列表 |
|
|
访问标识access_flags | 标志值 | 含义 |
---|---|---|
ACC_PUBLIC | 0x0001 | |
ACC_PRIVATE | 0x0002 | |
ACC_PROTECTED | 0x0004 | |
ACC_STATIC | 0x0008 | |
ACC_FINAL | 0x0010 | |
ACC_VOLATILE | 0x0040 | |
ACC_TRANSIENT | 0x0080 | |
ACC_SYNTHETIC | 0x1000 | 字段是否由编译器自动产生的 |
ACC_ENUM | 0x4000 | - |
接口中必有ACC_PUBLIC+ACC_STATIC_+ACC_FINAL标志
5.方法表集合
名称 | 类型 | 说明 |
---|---|---|
methods_count | u2 | 方法数量 |
methods[methods_count] | method_info | 方法集合 |
|
|
访问标识access_flags | 标志值 | 含义 |
---|---|---|
ACC_PUBLIC | 0x0001 | |
ACC_PRIVATE | 0x0002 | |
ACC_PROTECTED | 0x0004 | |
ACC_STATIC | 0x0008 | |
ACC_FINAL | 0x0010 | |
ACC_SYNCHRONIZED | 0x0020 | |
ACC_BRIDGE | 0x0040 | 方法是否有编译器产生的桥接方法 |
ACC_VARARGS | 0x0080 | 方法是否接受不定参数 例:void abc(String…a) |
ACC_NATIVE | 0x0100 | |
ACC_ABSTRACT | 0x0400 | |
ACC_STRICTFP | 0x0800 | 方法是否为strictfp |
ACC_SYNTHETIC | 0x1000 | 方法是否由编译器自动产生的 |
6.属性表集合
名称 | 类型 | 说明 |
---|---|---|
attributes_count | u2 | 属性数量 |
attributes[attributes_count] | attribute_info | 方法集合 |
|
|
属性名称 | 使用位置 | 含义 |
---|---|---|
Code | 方法表 | java代码编译成的字节码指令 |
ConstantValue | 字段表 | final关键字定义的常量值 |
Deprecated | 类、方法表、字段表 | 被声明为deprecated的方法和字段 |
Exceptions | 方法表 | 方法抛出的异常 |
省略…. | …. | …. |
文中概念:
- 字节码:以byte单位存储的文件
- 无符号数:属于基本数据类型,以u1、u2、u4、u8分别代表1、2、4、8个字节。用来描述数字、索引引用、数量值、按照utf-8编码的字符串值
- 表:由多个无符号数或者其他表作为数据项构成的复合数据类型,所有表都习惯性地以”_info”结尾。表用于描述有层次关系的复合结构的数据,整个Class文件本质上就是一张表
- 字面量(Literal):比较接近于Java语言层面的常量概念,如文本字符串、声明为final的常量值等
- 符号引用(Symbolic References):类和接口的全限定名(Fully Qualified Name),字段的名称和描述符(Descriptor),方法的名称和描述符
- 全限定名:org/fenixsoft/clazz/TestClass
- 简单名称:TestClass
- 描述符:描述字段的数据类型、方法的参数列表(包括数量、类型以及顺序)和返回值
标识描述符 | 含义 | 标识字符 | 含义 |
---|---|---|---|
B | byte | J | long |
C | char | S | short |
D | double | Z | boolean |
F | float | V | 特殊类型void |
I | int | L | 对象类型如Ljava/lang/Object |
[ | 数组的引用 | [[ | 二维数组的引用 |
读后感笔记来自周志明的《深入理解Java虚拟机(第2版)》