工具:【javap -verbose】 【Jclasslib】 【WinHex】
1.魔数(4字节,16进制)
- CA FE BA BE
2.副版本号,主版本号(4字节)
- 副版本号:Minor Version
- 主版本号:Major Version(45~57)
3.常量池计数器
- u2类型计数器
- 索引从1开始
- 索引0为不引用任何常量池项目
4.常量池数据区
- 字面量(Literal)(java语言层面的常量)
【文本字符串,被final修饰的常量】
public class Demo {
int i= 12;
String str = "asd";
}
//用javap -verbose 查看
//asd字符串在常量池 #14 = Utf8 asd
//而12是代码的一部分在<init> 5: bipush 12
- 符号引用(Symbolic References)(编译原理方面的概念)
【被模块导出或开放的包 package】
【类和接口的全限定类名】
【字段的名称和描述符】(字段名称,字段类型)
【方法的名称和描述符】(方法名称,返回类型,参数列表)
【方法的句柄和方法类型】
【动态调用点和动态常量】 - 编译器自动生成的常量(被字段表,方法表,属性表引用)
【< init >】【I】【V】【LineNumberTable】【LocalVariableTable】
注:
class文件不保存各个方法,字段(其他类的)在内存中的布局,而是使用符号引用。虚拟机类创建和运行时解析,翻译到具体的内存地址中。(类加载机制,解析过程,符号引用->直接引用)
5.访问标志
- 2个字节标识类或接口的访问信息
6.类索引
- 2个字节确定这个类的全限定类名
7.父类索引
- 2个字节确定这个类的父类的全限定类名
8.接口计数器
- u2类型计数器
9.接口信息数据区
- n个u2类型 存放CONSTANT_Class_info的索引
10.字段计数器
- u2类型计数器
11.字段信息数据区
- 访问标识,简单名称(常量池索引),描述符(字段类型)(常量池索引),属性表
- 描述符(字段类型):
String:[[Ljava/lang/String(二维数组)
Object:Ljava/lang/Object - 属性表 ConstantValue
12.方法计数器
- u2类型计数器
13.方法信息数据区
- 访问标识,方法名称(常量池索引),描述符(返回类型和参数列表)(常量池索引),属性表(方法的代码在code属性中)
- 描述符:先参数列表,后返回值
()V , ([CII[CIII)I
14.属性计数器
- u2类型计数器
15.属性信息数据区
- Code
More Actions类型 | 名称 | 数量 |
---|---|---|
u2 | attribute_name_index(固定code) | 1 |
u4 | attribute_length | 1 |
u2 | max_stack(操作数站深度) | 1 |
u2 | max_locals(局部变量表空间,变量槽) | 1 |
u4 | code_length(不超过u2) | 1 |
u1 | code | code_length |
u2 | exception_table_length | 1 |
exception_info | foexception_table | exception_table_length |
u2 | attributes_count | 1 |
attribute_info | attributes | attributes_count |
局部变量表存放:【方法参数(包括this对象)】【异常参数】【局部变量】
Code描述代码,其他为描述元数据
- ConstantValue
int x=123< init >
static int x=123< clinit >
final static int x=123< ConstantValue >
非Static类型变量在< init >中赋值(先父类构造,后这个,在this的构造)
final static 修饰基本类型和String 在< ConstantValue >
无final||不是基本类型和String < clinit >