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

类文件结构

啥是无关性?

  • JVM不仅具有平台无关性,还具有语言无关性。
  • 平台无关性是指不同操作系统都有各自的JVM。
  • 语言无关性是指Java虚拟机能运行除Java以外的代码!

无关性的基石

  • 平台无关性的基石:字节码
  • 语言无关性的基础:虚拟机和字节码存储格式

纵观Class文件结构

  • Class文件是一组以8位字节为基础单位的二进制流;各个数据项目严格按照顺序紧凑排列,中间无任何分隔符;遇到8位字节以上的时候按照高位在前分割。

  • Class文件采用一种类似C语言结构体的数据结构来存储数据,这种结构体中只有2中数据类型:无符号数和表

  • 无符号数:描述数字,索引引用,数量值或者按照UTF-8编码构成字符串值(u1、u2、u4、u8,分别代表1字节的无符号数…)
  • 表:描述有层次的复合结构的数据(顺序还是数量都是严格限定)

魔数与Class文件版本

  • 每个Class文件头4个字节称为魔数(Magic Number),确定这个文件是否是Class文件,固定为0xCAFEBABE。

  • 紧跟着魔数的4个字节存储了Class的版本号,JDK能向下兼容旧版本的Class文件,但不能向上兼容。

常量池

Class文件的资源仓库,与其他项目关联最多的数据类型。

  • 前置了u2类型的常量池容量计数器,很奇葩,从1开始(而不是0)

  • 常量分为两大类:

    • 字面量(Literal)
    • 类似于Java语言的常量,如文本字符串、final值等。
  • 符号引用(Symbolic References)

    • 类和接口的全限定名(Fully Qualified Name)
    • 字段的名称和描述符(Descriptor)
    • 方法的名称和描述符

访问标志

是Class类还是接口

  • 是否public
  • 是否abstract
  • 是否final等

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

都是u2类型

  • 确定了这个类的全限定名
  • 父类的全限定名
  • 接口的全限定名集合

字段表集合

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

方法表集合

与字段表几乎一致,依次包括访问标志、名称索引、描述符索引、属性表集合。

属性表集合

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

字节码指令简介

Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字(操作码)以及跟随其后的零至多个代表此操作所需参数(操作数)而构成。

  • Java虚拟机面向操作数栈而不是寄存器的架构
  • 大多数之类不包含操作数,只有一个操作码
  • 操作码长度为1个字节,即指令集操作码总数不能超过256条
  • 处理超过一个字节的数据时会重建,缺点是导致一定的性能损失,优点是省略很多填充和间隔符号

字节码与数据类型

大多指令有对应的数据类型,有特殊字符来助记

  • 指令集被故意设计成非完全独立(要不然操作码不够)
  • 大多数对于boolean,byte,short,char之类的数据操作,实际上都是使用int类型作为运算

加载和存储指令

用于数据在栈帧中的局部变量和操作数栈之间来回传输 > 有一部分是尖括号结尾的表示是一组之类(iload_<n>)

运算指令

用于对两个操作栈上的值进行某种特定运算

  • 大体分为两种(整数型数据&浮点型数据)
  • Java虚拟机没有明确规定数据溢出的具体运算结果 > 只有除法和求余指令中除数为0时会导致抛出ArithmeticException异常
  • Java虚拟机要求计算浮点数时,所有运算结果都必须舍入都适当的精度
  • Java虚拟机要求计算浮点数时,不会抛出任何异常

类型转换指令

将两种不同精度的数值类型进行互相转换

  • 宽化类型
    • int到long,float,double
    • long到float,double
    • float到double
  • 窄化类型
    • 必须显示使用转换指令,而且会造车精度的丢失

对象创建于访问指令

操作数栈管理指令

控制转移指令

方法调用和返回指令

异常处理指令

Java虚拟机中,处理异常不是由字节码指令来实现的,而是采用异常表来完成

同步指令

公有设计和私有设计

改进虚拟机的性能,主要是有两种方式:

  • 将输入的java虚拟机代码在加载或执行时翻译成另外一种虚拟机的指令集
  • 将输入的java虚拟机代码在加载或执行时翻译成宿主CPU的本地指令集(JIT)

Class文件结构的发展

  • Class文件结构一直处于稳定的状态,几乎没有改动
  • 所有对于其的改动都集中在访问标志,属性表这些设计上就可扩展上的内容
  • Class文件索所具备的平台中立、紧凑、稳定、可扩展的特点,是实现「平台」无关,「语言」无关的重要支柱。