第6章 java类文件结构

161 阅读4分钟

class 文件结构

  • 主要是理解class文件编译成字节码以后的存储方法
  • 本次讨论内容主要是class文件,不包括动态生成。
  • class文件整体上可以划分为Code和元数据,两部分

概述:

  • Class文件是以8位字节为基础单位的二进制流,jvm规范规定,class文件结构类似于c语言的伪结构体(包含两种数据结构)
    • 无符号数:基本数据类型。U1,U2,U4,U8分别代表1个字节,2个字节,4个字节和8个字节。
      • 描述数字,索引引用,数值量,或者按照UTF-8编码构成字符串值。
    • 表:由无符号数或者其他表作为数据项,组成的符合数据结构。
      • 描述有复合结构的数据。
      • 整个Class文件就是一张表。

一、魔数

  • class文件起始4个字节称为魔数
  • 不使用文件后缀区分是否是class文件,主要是基于安全考虑
  • tip:类加载过程中,一边加载一边进行验证,他们是同步进行的
  • 魔数值:0XCAFEBABE

二、版本号

  • 紧接着4个字节(5-8),(5-6)class文件次版本号,(7-8)文件主版本号
  • jvm拒绝执行超过自己版本号的class文件

三、常量池入口

  • 版本号之后,常量池入口(常量池大小不固定)

1、常量池:

  • class文件的资源仓库
  • class文件中最大的数据项目之一,也是和其他项目关联最多的数据类型
  • 入口放置一个U2类型数据, 代表常量池计数容量(从1开始,在0时表示不引用常量池任何一个值)

2、常量池中存放两大类常量:

  • 字面量
    • 接近java的常量概念,文本字符串,生命final的常量值(JDK1.8以后把String移到了堆中)
  • 符号引用
    • 类和接口的全限定名(包名+类名)
    • 字段的名称和描述符
    • 方法的名称和描述符
  • class文件中没有办法保存方法、字段的内存信息(Class只是一个文件)
    • 运行期间,常量池中的链接才能对应内存中的地址
    • 常量池中每一项都是一个表

四、访问标志

  • 常量池结束后,接着2个字节表示访问标志(类修饰符,类相关信息)
    • 类还是接口
    • 是否是public
    • 是否abstract
    • 如果是类的话,是否是final等等

五、类索引集合

  • 确定类的继承关系
    • 类索引和父类索引,都是U2类型
      • 类索引,确定这个类的全限定名
      • 父类索引,确定该类的父类全限定名
      • 除了Object外,所有类都有父类
    • 接口是一组U2类型的索引数据集合

六、字段表集合

  • 字段表描述接口或类中的变量(对象的成员变量)
  • 包括class级变量和obj级别变量。但不包括方法内的变量

七、方法表集合

  • 对方法的描述和对字段的描述完全一致
  • 方法表结构:
    • 访问标志(方法访问权限)
    • 名称索引
    • 描述符索引
    • 属性表集合 (方法的实现)

八、属性表集合

  • 概述:
    • 描述某些场景专有信息
    • class文件,字段表,方法表,都可以携带自己的方法表。

1、code属性

  • 出现在方法表的属性集合中
  • 接口和抽象类的抽象方法中就不存在code
  • this
    • 实例方法的局部变量表中,至少存在一个指向当前实例的局部变量
    • 局部变量表中也会预留出第一个slot位存放对象实例引用。

2、Exceptions属性

  • 列举方法中可能抛出的受检查的异常(throws 异常)

3、LineNumberTable属性

  • 描述java源码和字节码行号之间的对应

4、LocalVariableTable属性

  • 描述栈帧局部变量表中变量与java源码中定义变量的关系

5、contentValue属性

  • 通知虚拟机为static属性赋值
  • 为非static变量属性赋值(obj成员变量):
    • 实例构造器方法中进行
  • 为static变量赋值(class变量)
    • 被final和static共同修饰的基本数据类型和String用ContentValue保存

6、innerClass属性

  • 内部类和宿主类的关系

7、Deprecated及Synthic属性

  • Deprecated注解中的 @deprecated,表示该方法不推荐使用
  • Synthic不是java产生的,而是编译器自行产生的

8、StackMapTable属性

  • 复杂的变长属性,jvm加载字节码验证阶段被新类型验证器使用

9、Signature

  • 可选定长属性,出现于类、属性表、方发表的属性表中。
  • 主要是针对java使用伪泛型,反射困难,而增设

10、BootstrapMethod

  • 类文件的属性表中