JVM探索之路之Class文件结构解析(一):Class文件的格式与定义
JVM 学习笔记目录:
JVM探索之路之Class文件结构解析(三):访问修饰符、类索引、父类索引与接口索引集合
Class文件的格式与定义
Class文件是一组以8位字节(1Byte=8bit,计算机也有1Byte=16bit或1Byte=32bit的)为基础单位的二进制流,各个数据项目严格按照顺序紧凑的排列在Class文件之中,中间没有添加任何分隔符。当遇到需要占用8位字节以上空间的数据项时,则会按高位在前的方式分割成若干个8位字节进行存储。
Class文件结构中只有2种数据类型:无符号数和表。无符号数, 属于基本的数据类型,以u1、u2、u4、u8来分别表示1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值和UTF-8编码构成的字符串;表,是由多个无符号数或其他表作为数据项构成的复合数据类型,所有的表都习惯已"_info"结尾(整个Class文件可以看成是一张表)。
上图是Class文件的结构表,无论是无符号数还是表类型,当需要描述同一类型但数量不定的多个数据时。经常会使用一个前置的容量计数器加上若干个连续的数据项形式。例如:contant_pool_count、interfaces_count、fields_count、methods_count等都是前置容量计数器。
为了方便解释这些数据类型,提供一个非常简单的类作为例子来讲解:
package com.beliefbetrayal.clazz;
public class ClassFileTest {
private int m;
public int getM() {
return m;
}
public void setM(int m) {
this.m = m;
}
}
这个例子非常非常简单,定义一个类,它有一个成员变量和对应的get和set方法。现在我们找到该类对应的Class文件,使用WinHex(将二进制文件以16进制的形式打开,1Byte=8bit,所以2个16进制数表示一个字节)将Class文件打开。将会显示如下信息:
图为Class文件的部分信息
Class文件结构的第一个数据项目"magic",它的类型为u4(4个字节),所以0xCAFEBABE为它的值,该数据项称为"魔数",它的作用是用于确定这个文件是否为一个能被虚拟机接收的Class文件。而虚拟机使用魔数而不是用扩展名的机制来判断Class文件是出于安全的考虑,因为扩展名是可以随意修改的。你可以查看所有符合要求的Class文件它的魔数都是"0xCAFEBABE"。
Class文件结构第二个和第三个数据项目为:"minor_version"和"major_version" 分别表示Class文件的次要版本和主要版本信息。它们的类型都为u2(2个字节)所以0x0000表示次要版本,0x0032表示主要版本。Class文件的版本号是从45开始的,JDK1.1之后每一个JDK大版本发布主版本号就向上加1。JDK1.1能支持的版本号为45.0~45.65535的Class文件,JDK1.2能支持的版本号为46.0~46.65535以此类推,现在最新的JDK1.7能支持51.0~51.65535版本号的Class文件。还需要注意的一点是:高版本的JDK可以向下兼容以前版本的Class文件,但不能运行以后版本的Class文件。0x0032换算成十进制为50,按照上面的推导,该Class文件是可以被JDK1.6或以上的版本的虚拟机执行的Class文件(也可以反映出该Class文件是由JDK1.6版本的编译器编译的)。
下次分析:Class文件中的常量池(contant_pool)