“深入理解JVM:类文件结构”的版本间差异
跳到导航
跳到搜索
(→无关性的基石) |
|||
第19行: | 第19行: | ||
<pre> | <pre> | ||
任何一个Class文件都对应着唯一的一个类或接口的定义信息,但是反过来说,类或接口并不一定都得定义在文件里(譬如类或接口也可以动态生成,直接送入类加载器中)。 | |||
</pre> | |||
* Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中,'''中间没有添加任何分隔符'''。 | |||
根据《Java虚拟机规范》的规定,Class文件格式采用一种类似于C语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型: | |||
# “无符号数”:基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串值。 | |||
# “表”:由多个无符号数或者其他表作为数据项构成的复合数据类型,为了便于区分,所有表的命名都习惯性地以“_info”结尾。 | |||
#: 表用于描述有层次关系的复合结构的数据。 | |||
* 整个Class文件本质上也可以视作是一张表。 | |||
Class文件格式: | |||
:[[File:Class文件格式.jpg|400px]] | |||
如上图,Class的没有任何分隔符,其数据项的顺序、数量,甚至于数据存储的字节序(Byte Ordering,Class文件中字节序为Big-Endian)等,都是被严格限定的,哪个字节代表什么含义,长度是多少,先后顺序如何,全部都不允许改变。 | |||
=== 魔数、Class文件的版本 === | |||
魔数(Magic Number):每个Class文件的头4个字节被称为魔数(Magic Number),唯一作用是确定这个文件是否为一个能被虚拟机接受的Class文件。 | |||
* 很多文件格式标准中都有使用魔数来进行身份识别的习惯,因为相对于文件后缀更加安全;(譬如图片格式,如GIF或者JPEG等在文件头中都存有魔数) | |||
* Class文件的魔数为:“'''0xCAFEBABE'''(咖啡宝贝?)”; | |||
Class文件的版本号:紧接着魔数的4个字节存储的是Class文件的版本号; | |||
# 第5和第6个字节是次版本号(MinorVersion) | |||
# 第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文件。 | |||
示例: | |||
[[File:Java Class文件的结构.jpg|600px]] | |||
使用“WinHex”打开Class文件如上图: | |||
# 开头4个字节的十六进制表示是 0xCAFEBABE | |||
# 代表次版本号的第5个和第6个字节值为 0x0000,而主版本号的值为 0x0032,也即是十进制的50,该版本号说明这个是可以被JDK 6或以上版本虚拟机执行的Class文件。 | |||
Class文件版本号: | |||
: [[File:Class文件版本号.jpg|600px]] | |||
=== 常量池 === | === 常量池 === |
2020年10月25日 (日) 01:14的版本
无关性的基石
代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步。
- 无关性:即与平台无关,“一次编写,到处运行(Write Once,Run Anywhere)”;
- 无关性的基石:字节码(Byte Code):
- 各种不同平台的Java虚拟机,以及所有平台都统一支持的程序存储格式;
Java虚拟机不与包括Java语言在内的任何程序语言绑定,它只与“Class文件”这种特定的二进制文件格式所关联,Class文件中包含了Java虚拟机指令集、符号表以及若干其他辅助信息。
Class类文件的结构
任何一个Class文件都对应着唯一的一个类或接口的定义信息,但是反过来说,类或接口并不一定都得定义在文件里(譬如类或接口也可以动态生成,直接送入类加载器中)。
- Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符。
根据《Java虚拟机规范》的规定,Class文件格式采用一种类似于C语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:
- “无符号数”:基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串值。
- “表”:由多个无符号数或者其他表作为数据项构成的复合数据类型,为了便于区分,所有表的命名都习惯性地以“_info”结尾。
- 表用于描述有层次关系的复合结构的数据。
- 整个Class文件本质上也可以视作是一张表。
Class文件格式:
如上图,Class的没有任何分隔符,其数据项的顺序、数量,甚至于数据存储的字节序(Byte Ordering,Class文件中字节序为Big-Endian)等,都是被严格限定的,哪个字节代表什么含义,长度是多少,先后顺序如何,全部都不允许改变。
魔数、Class文件的版本
魔数(Magic Number):每个Class文件的头4个字节被称为魔数(Magic Number),唯一作用是确定这个文件是否为一个能被虚拟机接受的Class文件。
- 很多文件格式标准中都有使用魔数来进行身份识别的习惯,因为相对于文件后缀更加安全;(譬如图片格式,如GIF或者JPEG等在文件头中都存有魔数)
- Class文件的魔数为:“0xCAFEBABE(咖啡宝贝?)”;
Class文件的版本号:紧接着魔数的4个字节存储的是Class文件的版本号;
- 第5和第6个字节是次版本号(MinorVersion)
- 第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文件。
- 开头4个字节的十六进制表示是 0xCAFEBABE
- 代表次版本号的第5个和第6个字节值为 0x0000,而主版本号的值为 0x0032,也即是十进制的50,该版本号说明这个是可以被JDK 6或以上版本虚拟机执行的Class文件。
Class文件版本号:
常量池
访问标志
类索引、父类索引与接口索引集合
字段表集合
方法表集合
属性表集合
字节码指令简介
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 同步指令