class 文件结构
https://www.viralpatel.net/tutorial-java-class-file-format-revealed/
A Java class file is consist of 10 basic sections:
Magic Number: 0xCAFEBABE
Version of Class File Format: the minor and major versions of the class file
Constant Pool: Pool of constants for the class
Access Flags: for example whether the class is abstract, static, etc.
This Class: The name of the current class
Super Class: The name of the super class
Interfaces: Any interfaces in the class
Fields: Any fields in the class
Methods: Any methods in the class
Attributes: Any attributes of the class (for example the name of the sourcefile, etc.)
class文件由10个部分组成
- 魔数 Magic Number
- 版本号 minor &major versions
- 常量池 Constant Pool
- 类访问标记 Access Flags
- 类索引 This Class
- 超类索引 Super Class
- 接口表索引 Interfaces
- 字段表 Fields
- 方法表 Methods
- 属性表 Attributes
optimizing Java作者编了一句顺口溜
My Very Cute Animal Turns Savage In Full Moon Areas
我可爱的动物在满月时变得野蛮
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, World");
}
}
魔数
0xCAFEBABE 咖啡宝贝
0xCAFEBABE 是JVM识别 .class文件的标志,
还是有个CAFEDEAD魔数,用于对象持久化
版本号
这是里
0x 00 00 00 34 十六进制 转为十进制 52 java8
Major Version
java1.4 48
java 5 49
java 6 50
java7 51
java8 52
常量池
版本号之后就是常量池的区域
结构类似
struct{
u2 constant_pool_count; 常量池大小
cp_info constant_pool[constant_pool_count-1]
}
- 常量池的大小为n,真正有效的索引是 1~n-1,如果是10,就是1-9,0属于保留索引,可供特殊情况使用
- 常量池项cp_info集合,最多包含n-1个元素,因为long和double会占用2个索引位置
cp_info结构
cp_info{
u1 tag;
u1 info[];
}
cp_info的第一个字节表示常量项的类型tag,接下来的几个字节表示常量的具体内容。
目前JAVA虚拟机定义了14种常量tag类型,常量名都心CONSTANT开头
类型 | tag值 |
---|---|
-CONSTANT_Utf8_info- | 1 |
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 |
javap -v HelloWorld
Access flages
访问标志,用来标识一个类为final,abstrac,public 之类由2个字节表示
总共有16个标记位,可代使用,目前只使用了8个
标识位 | 标记 | 十六进制 | 描述 |
---|---|---|---|
0 | ACC_PUBLIC | 1 | 是否为public |
4 | ACC_FINAL | 10 | 是否为final |
5 | ACC_SUPER | 20 | 不再使用 |
9 | ACC_INTERFACE | 200 | 是类还是接口 |
10 | ACC_ABSTRACT | 400 | 是否为abstract |
12 | ACC_SYNTHETIC | 1000 | 编译器自动生成,不是用户源代码编译生成 |
13 | ACC_ANNOTATION | 2000 | 是否为注解 |
14 | ACC_ENUM | 1 | 是否为枚举类 |
this_class ,super_name,interfaces
表示继承关系
this_class表示类索引
super_name表示直接父类的索引
interfaces 表示类或者接口的直接父接口
字段表
struct{
u2 fields_count;
field_info fields[fields_count];
}
fields_count 表示数量
field_info 表示集合
field_info 结构
u2 access_flags; 访问标志
u2 name_index; 字段名
u2 descriptor_index; 字段描述索引,指向常量池的字符串常量
u2 attributes_count; 属性个数
attribute_info attributes[attributes_count]; 属性集合
- 第一部分 access_flags访问标记如ACC_PUBLIC(public)之类的
访问标记名 | 描述 |
---|---|
ACC_PUBLIC | 声明为public |
ACC_PRIVATE 声明为private | |
ACC_PROTOECTED | 声明为protected |
ACC_STATIC | 声明为static |
ACC_FINAL | 声明为final |
ACC_VOLATILE | 声明为volatile,解决内存可见性的问题 |
ACC_TRANSIENT | 声明为transient,被transient修饰的字段默认为被序列化 |
ACC_SYNITHETIC | 声明为这个字段由编译器生成 |
ACC_ENUM | 声明为枚举类型的变量 |
- 字段描述符
描述符 | 类型 |
---|---|
B | byte |
C | char |
D | double |
F | float |
I | int |
J | long |
S | short |
Z | boolean |
L ClassName; | 引用类型, L +对象类型的全限定名+“;" |
[ | 一维数组 |
- 字段属性
ConstantValue,Synthetic,Signature,Deprecated,RuntimeVisibleAnnotations,RuntimeInvisibleAnnotations 这6个
方法表
{
u2 method_count;
method_info methods[method_count];
}
method_count表示方法的数量
methods方法集合,共有method_count个方法
method_info 结构
u2 access_flags; 访问标志 private,public 之类
u2 name_index; 方法名
u2 descriptor_index; 方法描述索引,指向常量池的字符串常量
u2 attributes_count; 属性个数
attribute_info attributes[attributes_count]; 属性集合
属性表
u2 attributes_count;
attributes_info attributes[attributes_count];
attributes_count属性个数,attributes属性集合
attributes_info 结构
u2 attribute_name_index; 方法名 指向常量池的索引,可以得到attribute 名字
u4 attribute_length; 属性个数
u1 info[attribute_length]; 属性集合