Class 类文件结构
Class 文件是一组以 8 位为基础单位的二进制流,各个数据项目严格按照顺序排列在 Class 文件之中,中间没有任何分割符。若数据项占用空间超过 8 位,则按照高位在前 (Big-Endian) 的方式分割成多个 8 位存储。
前言
一本好书,每读一遍都会有不同的感受。写读书笔记,一来是便于平时查阅,毕竟技术书籍都比较厚,不方便随时携带;二来是督促自己多读书,理论与实践结合才能不断提升自己。
【深入理解Java虚拟机】阅读笔记: Class 类文件的结构
Class 文件结构
Class 文件格式采用类似于 C 语言结构体的伪结构来存储数据,包含两种数据类型:无符号数和表
无符号数属于基本的数据类型,以 u1、u2、u4、u8代表不同字节的无符号数
表是有多个无符号数或者其他表作为数据项构成的复合数据类型,一般以 “_info” 结尾
1 | graph TD |
Class 文件结构如下:
类型 | 名称 | 数量 |
---|---|---|
u4 | magic | 1 |
u2 | minor_version | 1 |
u2 | major_version | 1 |
u2 | constant_pool_count | 1 |
cp_info | constant_pool | constant_pool_count - 1 |
u2 | access_flags | 1 |
u2 | this_class | 1 |
u2 | super_class | 1 |
u2 | interfaces_count | 1 |
u2 | interfaces | interfaces_count |
u2 | fields_count | 1 |
field_info | fields | fields_count |
u2 | methods_count | 1 |
method_info | methods | methods_count |
u2 | attributes_count | 1 |
attribute_info | attributes | attributes_count |
代码
示例代码如下
1 | public class TestClass { |
Class 文件内容
1 | 00000000: cafe babe 0000 0034 0013 0a00 0400 0f09 .......4........ |
javap -verbose TestClass
1 | Classfile /Users/gorden5566/test/TestClass.class |
魔数与 Class 文件的版本
1 | 00000000: cafe babe 0000 0034 0013 0a00 0400 0f09 .......4........ |
头 4 个字节称为魔数 (Magic Number), 值为 0xCAFEBABE
第 5、6 个字节是次版本号 (Minor Version),第 7、8 个字节是主版本号 (Major Version)。Java 版本号从 45 (Java 1.1,十六进制 2D) 开始,Java 1.8 对应 52 (十六进制 34)
常量池
常量池容量计数从 1 开始,如本例中为十六进制 0x0013 (十进制 19) 表示有 18 项常量
可使用 javap -verbose
命令查看常量池内容
常量池每一项都是一个表,表开始的第一位是一个 u1 类型的标志位,各类型如下:
类型 | 标志 | 描述 |
---|---|---|
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 | 表示一个动态方法调用点 |
访问标志
访问标志大小为 u2,位于常量池之后
类索引、父类索引与接口索引集合
按顺序排列在访问标志之后
1 | 000000a0: 0300 0400 0000 0100 0200 0500 0600 0000 |
类索引为 3,父类索引为 4,接口索引集合为 0。对应常量如下
1 | #3 = Class #17 // TestClass |
参考
周志明. 深入理解Java虚拟机
- 2017-10-15
Java 虚拟机所管理的内存包括多个运行时数据区域,每个区都有自己的特点。
- 2017-10-22
Java 内存自动管理可归结为自动化地解决了两个问题:给对象分配内存以及回收分配给对象的内存。
- 2017-10-20
主要介绍常见垃圾收集算法的思想。
- 2017-10-16
在 Java 虚拟机规范的描述中,除了程序计数器外,虚拟机的其他几个运行时区域都有发生 OutOfMemoryError 异常的可能。
- 2017-10-20
在堆里面存放着 Java 世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”。