第六章-类文件结构

类文件结构包括

  1. 魔数与Class文件的版本
  2. 常量池
  3. 访问标志
  4. 类索引,父类索引与接口索引集合
  5. 字段表集合
  6. 方法表集合
  7. 属性表集合

第二节 无关性的基石

Java虚拟机不和包括Java在内的任何语言绑定,它只与“Class文件”这种特定的二进制文件格式所关联,Class文件中包含了Java虚拟机指令集符号表以及若干其他辅助信息。

基于安全方面考虑,Java虚拟机规范要求在Class文件中使用许多强制性语法结构化约束,但任一门功能性语言都可以表示为一个能被Java虚拟机所接受的有效的Class文件,Class的来源是何种语言

第三节 Class类文件的结构(*****本章重点)

ps:任何一个Class文件都对应着唯一一个类或接口的定义信息,但反过来类或接口并不一定都得定义在文件里。

Class文件时一组以8位字节为基础单位的二进制流,各个数据项目都严格按照顺序紧凑地排列在Class文件之中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。

Class文件格式采用伪结构来存储数据,伪结构中只有两种数据类型:无符号数和表

一 魔数与Class文件的版本

1 每个Class文件的头四个字节称为魔数,它的唯一作用是确定这份文件是否为一个能被虚拟机接受的Class文件

2 魔数的后四个字节存储的是Class文件的版本号:高版本的JDK能向下兼容以前的Class文件,但不能运行以后版本的Class文件

二 常量池

1 常量池可以理解为Class文件之中的资源仓库,它是Class文件结构中与其他项目关联最多的数据类型,也是占用Class文件空间最大的数据项目之一,同时它还是在Class文件中第一个出现的表类型的数据项目

2 由于常量池中常量的数量是不固定的,所以在常量池的入口需要放置一项u2类型的数据,代表的是常量池容量计数值,计数是从1开始的(这是一个特例要记得)

3 常量池主要存放两大类常量:字面量符号引用

字面量:文本字符串,声明为final的常量值等

符号引用包括:

  1. 类和接口的全限定名
  2. 字段的名称和描述符
  3. 方法的名称和描述符

当虚拟机运行时,需要从常量池获取对应的符号引用,再在类创建时或者运行时解析,翻译到具体的内存地址中

4 常量池中每一项常量都是一个表,一共有14种结构各不相同的表结构数据,它们的共同点是表开始的第一位是一个u1类型的标志位,代表当前这个常量属于哪种常量类型

5 UTF-8缩略编码与普通UTF-8编码的区别

三 访问标志

常量池结束之后,紧接着两个字节代表访问标志,这个标志用来识别一些类或者接口层次的访问信息,包括:这个Class是类还是接口,是否定义为public类型,是否定义为abstract类型,如果是类是否被声明为final等

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

类索引用于确定这个类的全限定名,父类索引用于确定这个父类的全限定名(只能有一个),接口索引集合用来描述这个类实现了哪些接口

五 字段表集合

1 字段表用于描述接口或者类中声明的变量,字段包括类级变量以及实例级变量,但不包括方法内声明的局部变量

2 区分全限定名简单名称方法和字段的描述符

全限定名是把类全名中的“.”替换为“/”

简单名称是指没有类型和参数修饰的方法或者字段名称

方法和字段描述符用来描述字段的数据类型,方法的参数列表和返回值

3 用描述符来描述方法时,按照先参数列表,后返回值的顺序来描述

4 对于字节码来讲,如果两个字段的描述符不一致,那字段重名也就是合法的

六 方法表集合

1 方法表包括了访问标志,名称索引,描述符索引,属性表集合

2 方法里面的代码去哪了?

方法里面额Java代码,经过编译器变异成字节码指令后,存放在方法属性表集合中一个名为“Code”的属性里面

3 特征签名:是一个方法中各个参数在常量池中的字段符号引用的集合,也就是返回值不会包含在特征签名中

4如果要重载一个方法,除了要与原方法具有相同的简单名称之外,还要求必须拥有一个与原方法不用的特征签名

七 属性表集合

在Class文件,字段表,方法表都可以携带自己的属性集合,以用于描述某些场景的专有信息

1 Code属性(****):上文已提到,Java程序方法体总的代码经过javac编译器处理后,最终变为字节码指令存储在Code属性中

Code属性表结构中的code用于存储字节码指令的一系列字节流,

code_length:编写Java代码时只要不是可以编写一个超长的方法来为难编译器,是不大可能超过这个最大值的限制

Code属性是Class文件中最重要的一个属性,Code属性用于描述代码

2 Java虚拟机执行字节码是基于的体系结构

3 在任何实例方法中里面,都可以通过“this”关键字访问到此方法所属对象,所以Args_size = 1;而声明为static的方法(静态方法或类方法)该参数值为0

4 字节码指令之后是这个方法的显式异常处理表集合,但对于Code属性表来说不是必须存在的

5 Exceptions属性的作用是列举出方法中可能抛出的受查异常

6 LineNumberTable属性:用于描述Java源码行号与字节码行号之间的对应关系,虽然不是运行时必要的属性,但默认会生成到Class文件之中(没有该属性的最主要影响就是当抛出异常时,堆栈中将不会显示出错的行号,并且在调试程序时,也无法按照源码行来设置断点)

猜你喜欢

转载自blog.csdn.net/wo8vqj68/article/details/81290853