Java把规范拆分成了《Java语言规范》、《Java虚拟机规范》,Java语言规范对应Java代码规范,Java虚拟机规范则对应Class文件。
平台无关性
各种不同平台的Java虚拟机,以及所有平台都统一支持的程序存储格式——字节码(Byte Code) 是构成平台无关性的基石。这种实现使得Java虚拟机规范通过只对Class文件这种特定的二进制文件负责,实现了Java虚拟机与Java语言独立,虚拟机只与Class文件相关,使得其他语言也可以通过特定编译生成class文件并在虚拟机上运行。
过程如下图:
通过class文件这个中间桥梁,使得Java虚拟机可以支持运行多种语言开发的程序变成了可能。
class文件定义
Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。当遇到需要占用8个字节以上空间的数据项时,则会按照高位在前的方式分割 成若干个8个字节进行存储。一般来说一个Class文件都对应着唯一的一个类或接口的定义信息。
用16进制方式打开一个class文件如下图:
如上图中间主要部分就是一个class文件的内容,文件通过二进制存储,以8个字节为一组,所以以16进制展示。
class文件结构组成
既然class文件要被虚拟机所理解,那么肯定class文件的结构必须固定,class文件按如下图结构排列。
结构如下图:
class文件中的内容按上图严格排列,其中类型u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个字节。*_info则表示有层次关系的复合结构的数据,每一种都有独立的结构,在每种数据的第一步都会标记占用的字节数。
class文件通过固定的数据结构排列顺序并且每种数据结构指定了占用的字节长度来紧凑的组成了完整的可读的文件,jvm只需要从文件开始的地方一步一步的读取就能够完全的解析出这个类文件的内容。
class文件简单解析
引入之前的图:
解析过程如下:
1、文件第一个结构是u4、magic,表示占用4个字节,表达文件的魔数。如上图内容部分前4个字节是“CA FE BA BE”,翻译过来就是咖啡宝贝,这是固定表示是class文件,就像png图片文件的前几个字节码一样,是作为表示的存在。
2、4个字节读取完成后表示magic这个结构完成,接下来开始下一个u2、minor_version,表示接下来的两个字节表示的是minor_version,不过这个字段好像一直没有使用,一直是0000。
3、minor_version后面紧接着的是u2、major_version,表示接下来两个字节表达的是major_version,代表的是jdk的主版本,上图的值是“00 34”转成十进制就是3*16+4=52,表示jdk8。jdk1.1对应的是45,1.2对应46,依次类推1.8对应52。如果执行class文件jvm的jdk版本低于编译class文件的jdk版本就会报错。比如:Unsupported major.minor version 52.0错误。
类文件的解析就像这样按结构和结构占用的字节一段一段的分析,不过上面是才开始比较简单,后面更加复杂,后面再来慢慢学习吧。
总结
JVM并不是天经地义的运行我们的Java程序,而是通过对class文件加载来读取的,很多语言都可以通过特殊的编译生成class文件,只要编译的class文件符合Java虚拟机规范的要求都可以加载成功。不过Java程序和class文件还是最相近的,通过学习class文件我们可以更加清晰的认识平时所写代码最终变成的什么样子。
今天只分析了class文件前面三个基础结构,后面结构更加复杂,后面在慢慢整理!
Java程序员日常学习笔记,如理解有误欢迎各位交流讨论!