世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程。
- .class文件是以8字节为单位的紧凑排列的二进制流,对格式有严格的要求
- class文件格式稳定,有很好的的向后兼容性。并且JVM不允许执行高版本的class文件
- class文件只有两种数据类型:无符号数和表
- 无符号数:u1、u2、u4、u8,分别代表1、2、4、8个字节
- 表:由多个无符号数或表组和而成
- 描述某一类型连续数据时(集合):容量计数器+数据项
- 魔数(u4):0xCAFEBABE,用来判断文件类型为class文件
- 次版本号(u2)(Minor Version):5、6字节
- 主版本号(u2)(Major Version):7、8字节
- java主版本号从45开始,JDK1.1 - 45,JDK13 - 57
- 常量池:class文件的资源仓库
- 常量池容量计数(u2)是从1开始的(其他都是从0)
- 常量池有两种类型的常量:字面量和符号引用
- 字面量:文本字符串、final常量
- 符号引用:
被模块导出或开放的包
类和接口的全限定名
方法的名称和描述符
方法句柄和方法类型
动态调用点和动态常量 - 对于符号引用,在JVM类加载时才分配内存地址
- 常量池中每一个常量都是一个表
- 截止JDK13,常量池中分别有17种不同类型的常量
- 每个常量表第一位都是tag(u1)标志位,表示常量类型
- 访问标志(u2) :类或接口的访问信息
ACC_PUBLIC
ACC_FINAL
ACC_SUPER
ACC_INTERFACE
ACC_ABSTRACT
ACC_SYNTHETIC
ACC_ANNOTATION
ACC_ENUM
ACC_MODULE
access_flags一共有16个标志位,现在使用了其中的9个
其他清零
21. 类索引(u2)、父类索引(u2)、接口索引(u2)集合:确定类的继承关系
类索引 - 类的全限定名
父类索引 - 父类的全限定名
查找全限定名的过程:
索引 -> (常量池)CONSTANT_Class_info -> (常量池)CONSTANT_Utf8_info = 类的全限定名
接口索引 - 实现了哪些接口,从左到右的集合
结构:接口计数器,接口
22. 字段表:静态变量和实例变量
字段表结构
access_flags
name_index
descriptor_index
access_flags
ACC_PUBLIC
ACC_PRIVATE
ACC_PROTECTED
ACC_FINAL
ACC_STATIC
ACC_VOLATILE
ACC_TRANSIENT
ACC_SYNTHETIC
ACC_ENUM
name_index(对常量池的引用):字段简单名称
name_index -> CONSTANT_Utf8_info
descriptor_index(描述符):字段的类型、方法的参数列表和返回值。
描述符表示:
基本数据类型和void都使用一个字母表示:
byte: B
char: C
short: S
int: I
long: J
float: F
double: D
boolean: Z
void: V
对象:L + 类的全限定名
数组:[
描述符实例:
int fun(char[][] chars, int a) {}
([[CI)I
属性表集合 - 存储额外信息
字段表集合中不会列出从父类或父接口中继承的字段
java中字段不支持重载
class文件中只要描述符不同,字段名相同也认为是合法的