深入Java虚拟机笔记(三):类文件结构

时间:2021-05-25 14:03:33

介绍

各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节码是构成平台无关性的基础,实现语言的无关性还是虚拟机和字节码存储格式,所以Java编译可以把Java代码编译为存储字节码的Class文件,Java虚拟机不管Class的来源是什么,反正符合Class文件结构就可以在Java虚拟机运行。

深入Java虚拟机笔记(三):类文件结构

所有表都习惯性以“_info”结尾,表用于描述有层次关系的复合结构的数据,整个Class文件本质就是一张表

魔数与Class文件的版本

每个Class文件的头4个字节称为魔数,用于确定这个文件是否一个能被虚拟机接受的Class文件,CLass文件的魔数是CAFEBABE(咖啡宝贝),其他文件存储格式也使用魔数来进行身份识别,譬如图片格式。魔数后4个字节存储的Class文件的版本号
深入Java虚拟机笔记(三):类文件结构

常量池

紧接在主次版本后面之后的是常量池入口,常量池是Class文件结构与其他项目关联最多的数据类型,也是占用Class文件空间最大的数据项目之一。常量池还放置常量池容量计数值,来统计常量的数量
常量池主要存放两大类常量字面量和符号引用,字面量比较接近与Java语言层面的常量概念,如文本字符串,被声明为final的常量值相等,而符号引用属于编译原理方面的概念,包括了下面三类常量:
1、类和接口的全限定名
2、字段的名称和描述符号
3、方法的名称和描述符

常量池中的每一项常量都是一个表,共有11种
深入Java虚拟机笔记(三):类文件结构

再看第7的CONSTANT_Class_info
深入Java虚拟机笔记(三):类文件结构

name_index是一个索引值,指向常量池一个CONSTANT_Utf8_info类型的常量,该常量代表这个类的全限定名
深入Java虚拟机笔记(三):类文件结构

Class文件中方法、字段等都需要引用CONSTANT_Utf8_info型常量来描述名称,所以CONSTANT_Utf8_info型常量length的最大长度也就Java中方法和字段名的最大长度

访问标志

在常量池之后的2个字节代表访问标志,用于识别一些类或者接口层次的访问信息,
深入Java虚拟机笔记(三):类文件结构

类索引、父类索引与接口索引集合

类索引、父类索引都是一个u2类型的数据,分别指定这个类的全限定名和其父类的全限定名,而接口索引集合是一组u2类型的数据的集合,Class文件中由这三项数据确定这个类的继承关系
深入Java虚拟机笔记(三):类文件结构

字段表集合

描述接口或类中声明的变量,字段(field)包括了类级变量或实例变量,但不包括方法内部声明的变量。

描述一个字段的信息有:字段的作用域(public,private,protected修饰符),是类级变量还是实例级变量(static修饰符),可变性(final),并发可见性(volatile修饰符,是否强制从主内存读写),是否可序列化(transient修饰符),字段数据类型(基本数据类型,对象,数组),字段名称。这些信息中,各个修改符都是布尔值,很适合使用标志位来表示。而字段叫什么名字,只能引用常量池中的常量来描述。

方法表集合

方法表的结构与字段表一样,依次包含了访问标志(access_flags),名称索引(name_index),描述符索引(descriptor_index),属性表集合(attributes)几项
深入Java虚拟机笔记(三):类文件结构

深入Java虚拟机笔记(三):类文件结构
在Java语言中,要重(Override)一个方法,除了要与原方法具有相同的简单名称之外,还要求必须拥有一个与原方法不同的特征签名,特征签名是一个方法中各个参数在常量池中的字段符号引用的集合,也就是因为返回值不会包在特征签名之中,因为Java语言里是无法仅仅依靠返回值的不同来对一个已有的方法进行重载的。

属性表集合

在Class文件,字段表,方法表中都可以携带自己的属性表集合,以用于描述某些场景专有的信息。
深入Java虚拟机笔记(三):类文件结构