深入理解JVM:类文件结构

来自Wikioe
跳到导航 跳到搜索


无关性的基石

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


  • 无关性:即与平台无关,“一次编写,到处运行(Write Once,Run Anywhere)”;
  • 无关性的基石:字节码(Byte Code):
    各种不同平台的Java虚拟机,以及所有平台都统一支持的程序存储格式;


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

Java虚拟机提供的语言无关性.jpg

Class类文件的结构

   任何一个Class文件都对应着唯一的一个类或接口的定义信息,但是反过来说,类或接口并不一定都得定义在文件里(譬如类或接口也可以动态生成,直接送入类加载器中)。
  • Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符

根据《Java虚拟机规范》的规定,Class文件格式采用一种类似于C语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:

  1. “无符号数”:基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串值。
  2. “表”:由多个无符号数或者其他表作为数据项构成的复合数据类型,为了便于区分,所有表的命名都习惯性地以“_info”结尾。
    表用于描述有层次关系的复合结构的数据。
  • 整个Class文件本质上也可以视作是一张表。


Class文件格式:

Class文件格式.jpg

如上图,Class的没有任何分隔符,其数据项的顺序、数量,甚至于数据存储的字节序(Byte Ordering,Class文件中字节序为Big-Endian)等,都是被严格限定的,哪个字节代表什么含义,长度是多少,先后顺序如何,全部都不允许改变。


魔数、Class文件的版本

魔数(Magic Number):每个Class文件的头4个字节被称为魔数(Magic Number),唯一作用是确定这个文件是否为一个能被虚拟机接受的Class文件。

  • 很多文件格式标准中都有使用魔数来进行身份识别的习惯,因为相对于文件后缀更加安全;(譬如图片格式,如GIF或者JPEG等在文件头中都存有魔数)
  • Class文件的魔数为:“0xCAFEBABE(咖啡宝贝?)”;


Class文件的版本号:紧接着魔数的4个字节存储的是Class文件的版本号;

  1. 第5和第6个字节是次版本号(MinorVersion)
  2. 第7和第8个字节是主版本号(Major Version)
  • Java的版本号是从45开始;
  • 高版本的JDK能向下兼容以前版本的Class文件,但不能运行以后版本的Class文件;
    如:JDK 1.1能支持版本号为45.0~45.65535的Class文件,无法执行版本号为46.0以上的Class文件,而JDK 1.2则能支持45.0~46.65535的Class文件。


示例: Java Class文件的结构.jpg 使用“WinHex”打开Class文件如上图:

  1. 开头4个字节的十六进制表示是 0xCAFEBABE
  2. 代表次版本号的第5个和第6个字节值为 0x0000,而主版本号的值为 0x0032,也即是十进制的50,该版本号说明这个是可以被JDK 6或以上版本虚拟机执行的Class文件。


Class文件版本号:

Class文件版本号.jpg

常量池

访问标志

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

字段表集合

方法表集合

属性表集合

字节码指令简介

6.4.1 字节码与数据类型 6.4.2 加载和存储指令 6.4.3 运算指令 6.4.4 类型转换指令 6.4.5 对象创建与访问指令 6.4.6 操作数栈管理指令 6.4.7 控制转移指令 6.4.8 方法调用和返回指令 6.4.9 异常处理指令 6.4.10 同步指令

公有设计,私有实现

Class文件结构的发展