JAVA虚拟机【类文件结构】

代码编译的结果从本地机器吗转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步。

1. 无关性的基石:

各种平台的虚拟机都统一使用字节码作为程序存储格式,这是平台无关的基石。同时,语言无关性也在被开发者所重视,JAVA虚拟机同样可以运行其它的程序。

2. class文件结构:

Class文件是以8位字节为基础单位的二进制流,中间没有分隔符,所以整个Class文件都是程序运行的必要元素。

Class文件以一种伪结构来存储数据,包括:无符号数和表。无符号数属于基本数据类型,以u1,u2,u4,u8代表1字节,2字节,4字节和8字节的无符号数。可以用来描述数字,索引引用,数量值或者按照utf-8编码的字符串值。表是由多个无符号数或者其他表构成的符合结构的数据。

2.1 魔数与Class文件版本

头4个字节称为魔数,唯一作用就是确认这个文件是否为一个能够被虚拟机接受的Class文件。0xCAFEBABE就是JAVA文件的魔数。5,6字节是次版本号,7,8是主版本号。

2.2 常量池

接着版本号后,就是常量池。常量池的入口处放置一项u2类型的数据,代表常量池的计数值。该计数值从1开始,如果是22,则表示总共有21个常量,索引范围1~21。

常量池中有两类常量:字面量和符号引用。字面量就是常常口中说的常量,包括字符串,数字等等。符号引用包括类和接口的全限定名,字段和名称的描述符,方法和名称的描述符三类。

常量池的项目类型如下:

每一种项目类型会有不同的数据结构,比如UTF8编码的字符串常量的格式就如下:

2.3 访问标志

常量池结束后紧跟着两个字节表示访问标志。常用标志如下:

2.4 类索引,父类索引与接口索引集合

前两个都是u2类型的数据,类索引用于确定类的全限定名,父类索引用于确定父类的全限定名,接口索引集合用来描述这个类实现了哪些接口。接口索引第一项,接口计数器表示索引表的容量。

2.5 字段表集合

包括类级变量,实例级变量,不包括方法声明的局部变量。字段表的结构如下:

全限定名包括路径,之间用/表示,简单名字只有一个名字。描述符描述字段的数据类型,方法的参数列表和返回值。

2.6 方法表集合

结构如下:

2.7 属性表集合

2.7.1 code属性

其中code用来存储JAVA源程序编译后生成的字节码命令。每个指令由一个u1的字节码表示,即字节码最多有256条命令 。

code属性是字节码中最重要的属性,JAVA程序分为代码和元数据,Code属性用于描述代码,所有其他数据项目用于描述元数据。

2.7.2 Exceptions属性

这里的Excepetions属性是与方法平级的一项属性,与Code属性中的异常表不同。

2.7.3 LineNumber属性(非必须)

用与描述JAVA源码行号与字节码行号之间的对应关系。

2.7.4 LocalVariableTable属性(非必须)

用于描述栈帧中局部变量表中的变量与JAVA源码中定义的变量之间的关系。

2.7.5 SourceFile属性(非必须)

用于记录生成这个Class文件的源码文件名称。对于一些类名与文件名不一致的情况,不用这个属性,当抛出异常的时候,无法定位到出错代码的文件名。

2.7.6 ConstantValue属性

用于通知虚拟机自动为静态变量赋值。

2.7.7 InnerClasses属性

用于记录内部类和宿主类之间的关联。

2.7.8 Deprecated和Synthetic属性

Deprecated属性用于表示某个类,字段或者方法已经被程序定为不再使用。

Synthetic属性用于代表此方法或者字段并不是由JAVA源码产生的,而是编译器自己产生的。

2.7.9 StackMapTable属性

在虚拟机类加载字节码验证阶段被新类型检查验证器使用。

2.7.10 Signature属性

任何类、接口、初始化方法或成员的泛型签名如果包含了类型变量或参数化类型,则Signature属性会为他记录泛型签名信息。

2.7.11 BootstrapMethods属性

用于保存incokedynamic指令引用的引导方法限定符。

发布了73 篇原创文章 · 获赞 11 · 访问量 9480

猜你喜欢

转载自blog.csdn.net/fanyuwgy/article/details/103825313
今日推荐