对《深入理解Java虚拟机》一书的类文件结构进行总结(不关注细节,只总结):
一般一个类或者一个接口就对应一个class文件,但有的类是用类加载器直接生成的,这些类就没有class文件
那么,class文件中都存储了些什么呢?
1.class文件的版本信息
用开头4个字节存储,又称为“魔数”
2.常量池
常量池又分为字面量和符号引用。
字面量接近于java中的常量,例如文本字符串、声明为final的常量等;
符号引用包括了:
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
在存储常量池时,首先存一个常量池容量计数器,用以指示其中常量的个数;然后其中的每个字面量/符号引用都用一个表来描述。(class是一组以8位字节问基础单位的二进制文件,也许是为了节省空间,没有任何分割符,各个数据项目严格按照既定的格式顺序排列,因此其中涉及到的池、集合等,在开头总有一个容量计数器,说明集合容量)
- 如果是简单的字面量,就直接在表中对其内容进行描述
- 如果是符号引用,就在其中用一个name_index索引值来指向一个字面量,这个字面量中再存储具体的内容
3.访问标志
标识一些类/接口层次的信息,例如这个class是类还是接口?该类是否有abstruct修饰?是否有final修饰?等等
4.类索引、父类索引和接口索引集合
这三个东西用以描述类的继承关系。
类索引用于确定这个类的全限定名。(它只是一个索引,指向符号引用、符号引用再指向字面量)
父类索引用于确定这个类的父类的全限定名。
接口索引集合用于确定这个类实现了哪些接口。其存储的思想和池的存储类似。
5.字段表集合
描述类或接口中声明的变量。
变量声明中有没有用static、final等类似的修饰符,可以用一个位来存储,称为标志位
而变量的字段名、所用域(private/public/protected)无法用一个简单的位表示,转而用常量池中的符号引用表示。
6.方法表集合
首先仍然是容量计数器,存储方法数量
然后是方法表,包含了:访问标志、名称索引、描述符索引、属性表集合。前三个概念可以参考字段表。最后一个属性表中,存放包括了程序方法体的代码编译后形成的字节码。