Java类文件结构
Java编译器把源代码(.java文件)编译成字节码(.class文件),class文件是平台无关的,通过JVM加载后运行。
类文件结构
Java虚拟机规范中规定以u1、u2、u4、u8表示相应字节的无符号数,多个无符号数可以构成表(类似于C的结构体)
| 类型 | 名称 | 说明 |
|---|---|---|
| u4 | magic | 魔数,固定值0xCAFEBABE |
| u2 | minor_version | 次版本号 |
| u2 | major_version | 主版本号,1.1以前是45,后面每个版本+1,Java8是52 |
| u2 | constant_pool_count | 常量池长度 |
| cp_info | constant_pool | 长度是constant_pool_count-1,主要存放字面量和符号引用 |
| u2 | access_flags | 访问标志,用于标志这个类是否为接口、抽象类、注解、枚举、final、public等 |
| u2 | this_class | 类的全限定名索引,指向常量池 |
| u2 | super_class | 父类全限定名索引,指向常量池 |
| u2 | interfaces_count | 实现的接口个数 |
| u2 | interfaces | 实现的接口索引,指向常量池 |
| u2 | fields_count | 类字段数量 |
| field_info | fields | 包括类变量和实例变量,不包括方法内的局部变量 |
| u2 | methods_count | 方法个数 |
| method_info | methods | 方法具体描述 |
| u2 | attributes_count | 属性长度 |
| attribute_info | attributes | 属性具体描述 |
常量池
常量池相对于其他比较特殊,下标从1开始。
字面量(Literal):类似于Java的常量,例如文本字符串、final常量值等。
符号引用(Symbolic References):主要包括类和接口的全限定名、字段名称和描述符、方法名称和描述符
在Java7的常量池中共有14种常量类型:

提示
由于方法名、字段名、字符串字面量等都要引用CONSTANT_Utf8_info类型常量,而其中的length使用的u2类型能表示的最大值为65535,所以方法名、字段名、字符串字面量等的最大长度是64KB
字段表结构
| 类型 | 名称 | 说明 |
|---|---|---|
| u2 | access_flags | 字段访问标志,public、static、final、volatile、transient、enum等 |
| u2 | name_index | 字段名称索引 |
| u2 | descriptor_index | 字段描述符索引 |
| u2 | attributes_count | 属性长度 |
| attribute_info | attributes |
提示
字段表集合中不会列出从父类继承的字段
其中描述符用于描述字段的数据类型、方法的参数列表和返回值。在描述符中,基本类型byte/char/double/float/int/short以及void都分别用大写首字母表示,而long表示为J、boolean表示为Z、对象类型表示为“L+全限定名+;”。数组的每个维度用“[”字符表示。
用描述符描述方法时,按照先参数列表后返回值的顺序描述,参数列表放在小括号“()”内。例如方法gggg(int, int, char, java.lang.String[])的描述符是(IIC[Ljava/lang/String;)V
字段表中可以包含0~n项属性表,例如字段定义为final static int m = 123,则会包含一个ConstantValue属性表,详见属性表结构
方法表结构
方法表的结构与字段表基本相同,这是访问标志的取值稍有区别,而方法体的代码则保存在属性表的“Code”属性表中 。
与字段表相同,如果父类方法没有在子类中重写(Override),则方法表中就不会列出父类的方法,但可能会出现由编译器自动添加的方法,例如类构造器<clinit>方法和实例构造器<init>方法。
属性表结构
在类、字段、和方法中都会引用属性表,Java虚拟机规范第7版中预定义了21种属性表。常用的属性表如下:

Code属性表
| 类型 | 名称 | 说明 |
|---|---|---|
| u2 | attribute_name_index | 属性名索引,指向utf8类型,固定值“Code” |
| u4 | attribute_length | 属性值长度 |
| u2 | max_stack | 操作数栈深度的最大值 |
| u2 | max_locals | 局部变量表所需的存储空间,单位是Slot=4Byte |
| u4 | code_length | 字节码指令的长度 |
| u1 | code | 字节码指令,长度为code_length,在虚拟机规范中规定最大长度是65535 |
| u2 | exception_table_length | |
| exception_info | exception_table | 显式异常处理表 |
| u2 | attributes_count | |
| attribute_info | attributes |
字节码分析工具
提示
jdk中的javap工具可以用于分析class字节码