一:class类文件
class类文件实际上是二进制(字节码)文件格式,class文件中包含了java虚拟机指令集和符号表以及若干其他辅助信息。实际上虚拟机载入和执行同一种平台无关的字节码(class文件),实现了平台无关性。
二:class类文件结构
class文件是一组以8位字节位基础单位的二进制流。它采用类似c语言中的结构体一样的伪结构体来存储数据,这种伪结构只有两种数据类型:无符号数和表。无符号表以u1,u2,u3,u4,u8来代表1字节。2字节,4字节和8字节,无符号数可以用来描述数字,索引引用,数量值或者按照UTF-8编码构成字符串值。表是由多个无符号数或者其他表作为数据项构成的复合数据类型。
class文件的结构:
1.0~4字节:魔数,用来确定该class文件是否为一个能被虚拟机接受的class文件。
2. 5~6字节:表示次版本号。
3. 7~8字节:表示主版本号
4. 常量池:常量池主要存放两大类常量,字面量和符号引用。字面量比较接近java语言层面的常量概念,如文本字符串,声明为final的常量值等。而符号引用则属于编译原理方面的概念,包括类和接口的全限定名,字段的名称和描述符以及方法的名称和描述符。当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或运行时解析,翻译到具体的内存地址之中。常量池中的每一项常量都是一个表,一共有14种不同结构各不相同的表结构数据。(比如整型,浮点型,长整型等等字面量)。
我们可以通过一个专门的分析class文件字节码的工具:javap,它是由oracle公司准备的在JDK的bin目录中,可以使用javap工具的-verbose参数输出的某class文件字节码内容。(命令:javap -verbose xx)
5.访问标志:占用两个字节,用于识别一些类或者接口层次的访问信息,包括这个class是类还是接口,是否定义为public类型,是否定义为abstract类型,如果是类的话,是否被声明为final等。
6. 类索引,父类索引与接口索引集合:类索引和父类索引都是一个u2类型的数据,而接口索引是一组u2类型的数据的集合。class文件通过这三个数据项来确定这个类的继承关系。类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名。接口索引集合用来描述这个类实现了哪些接口,这些被实现的接口将按照implement语句后的接口顺序从左到右排列在接口索引集合中。
7. 字段表集合:用于描述接口或者类中声明的变量,字段包括类级变量以及实例级变量,但不包括在方法内部声明的局部变量。可以包含字段的作用域,是实例变量还是类变量(static修饰符),可变性(final),并发可见性(volatile修饰符,是否强制从主内存读写),可否被序列化(transient修饰符),字段数据类型(基本类型,对象,数组),字段名称。
8. 方法表集合:包括了访问标志,名称索引,描述符索引,属性表集合几项,除此之外,方法里面的代码经过编译器编译成字节码指令之后,存放在方法属性表集合中一个名为”code”的属性里面。
9. 属性表集合:在class文件,字段表,方法表都可以携带自己的属性表集合,用于描述某些场景专有的信息。它不再要求各个属性表具有严格的顺序,并且只要不与已有属性名重复就可以。预定义属性已经增加到了21项。