Class类文件的结构
各种不同平台的虚拟机与所有平台都统一使用的程序存储格式---字节码(ByteCode)是构成平台无关性的基石。Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件之中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。
魔数(Magic Number):Class文件的头4个字节,唯一作用是确定这个文件是否为一个能被虚拟机接受的Class文件。高版本的JDK能向下兼容以前版本的Class文件,但不能运行以后版本的Class文件。
常量池(Constant Pool):是Class文件之中的资源仓库,是Class文件结构中与其他项目关联最多的数据类型,也是占用Class文件空间最大的数据项目之一,同时它还是在Class文件中第一个出现的表类型数据项目。常量池的容量计数是从1开始,对于其他集合类型,包括接口索引集合、字段表集合、方法表集合等的容量计数都是从0开始。常量池中主要存放字面量(Literal)和符号引用(Symbolic References)(符号引用包括类和接口的全限定名(Fully Qualified Name)、字段的名称和描述符(Descriptor)、方法的名称和描述符)。
访问标志(Access Flags):占用两个字节,用于识别一些类或接口层次的访问信息。如这个Class是类还是接口,是否定义为public类型,是否定义为abstract类型,如果是类的话,是否被声明为final等。
类索引(this_class)、父类索引(super_class)与接口索引集合(interfaces):类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名,接口索引集合用来描述这个类实现了哪些接口。
字段表集合(field_info):用于描述接口或者类中声明的变量。字段包括类级变量以及实例级变量,但不包括在方法内部声明的局部变量。
方法表集合:与字段的描述几乎完全一致,结构如同字段表一样,依次包括访问标志(access_flags)、名称索引(name_index)、描述符索引(descriptor_index)、属性表集合(attributes)。
属性表集合:在Class文件、字段表、方法表中都可以携带自己的属性表集合,以用于描述某些场景专有的信息。属性表集合不要求各个属性具有严格顺序,只要不与已有属性名重复即可,Java虚拟机运行时会忽略掉它不认识的属性。关键常用属性有:Code属性、Exceptions属性、LineNumberTable属性、LocalVariableTable属性、SourceFile属性、ConstantValue属性、InnerClasses属性、Deprecated及Synthetic属性、StackMapTable属性、Signature属性、BootstrapMethods属性。
公有设计和私有实现:公有设计指的是规定的Java虚拟机规范;私有实现是指在满足虚拟机规范的约束下对具体实现做出修改和优化以实现一个优秀的虚拟机。只要优化后Class文件依然可以被正确读取,并且包含在其中的语义能得到完整的保持,那实现者就可以选择任何方式去实现这些语义。虚拟机实现的方式主要有两种:(1)将输入的Java虚拟机代码在加载或执行时翻译成另外一种虚拟机的指令集;(2)将输入的Java虚拟机代码在加载或执行时翻译成宿主机CPU的本地指令集(即JIT代码生成技术)。