在学习该小节内容之前建议大家下载工具JBE,它是一个Java字节码编辑器,能够浏览和编辑Java字节码。在学习的过程中可以使用该工具亲自探索,从而加深理解。


Java字节码类文件(.class)是Java编译器编译Java源文件(.java)产生的“目标文件”。无论使用的Java编译器具体如何实现,其编译之后的Java字节码类文件(.class)应该在任何JVM上运行。





记得大学教程里面的冯•诺伊曼(电脑之父啊)架构(当然现代计算机已经有了很多变化,例如非冯•诺伊曼架构系列等,但多为在冯•诺伊曼架构基础上的改进)吗?




---------------------------------------------------------------------------------------



其实我一直在思考技术和哲学(不是技术哲学)之间的关系,当我们把技术刨根问底的时候,总是发现它是那么的哲学,难道真正的“圣人”就是一个刚出生的“婴儿”?其实在计算机运算上追求的是一种“精妙的简”(在大量采用二进制之前有采用10进制和3进制的计算机),一个要“表象万物”的东西一定要“简”,就像技术哲学中的原子假设一样可以预知未来(这不是算命吗?周易八卦?),这种“简”能够“自我复制和繁衍”(冯•诺伊曼在参与计算机研制之前搞原子弹制造)。



---------------------------------------------------------------------------------------





冯•诺伊曼架构的存储程式提出程序是由一系列的指令和数据组成的,并且是线形地址编码存储的 (这个基本的归真思路,能帮助我们理解C/C++,Java等各种语言的编译、连接、执行的基本原理)






java字节码文件的后缀名称 java字节码文件的扩展名_平台

查看大图





冯·诺依曼存储程式结构





上图表达的归真思路就是最终的可执行程序文件是扁平的(即线形地址编码的),程序执行的过程就是不断向CPU发送指令和CPU不断从存储设备中读取数据的过程,直到特定的终止条件发生。指令+数据更人性化地可以说是算法+数据结构(让我想起数据结构教程中的这句话,所以加进来了)。例如Java语言中类结构、变量、数组、引用、实例等就是“数据”,而各种操作符和控制符就是“指令”。





同样,Java字节码类文件(.class)的格式包括两部分:数据+指令。





我们先来粗略的谈谈数据部分(即Java字节码类文件的格式,其中包含指令内容,但从文件格式层面来说指令也用数据来表示,正如后面内容介绍的指令=操作码+操作数):





Java字节码类文件由一系列的8位字节码流组成,16位、32位和64位都是通过8位字节码大数在前的方式(Big-endian,例如16位字符的表示前8位是高位,后8位是低位)表示。





Java字节码类文件的具体结构如下(u2,u4分别代表无符号两字节、四字节空间,符合Big-endian表示):






java字节码文件的后缀名称 java字节码文件的扩展名_jvm_02





Java字节码类文件格式结构





通过上面的结构我们可以了解Java字节码类文件的结构,我不打算逐一介绍(在JVM抽象架构部分会更进一步提到该内容,如果首次接触不是很理解,可以框架性的了解即可),只对重点但又难以理解的内容进行补充说明,在抓住重点和基本框架的基础上细节可以通过教程JVM规范第二版 http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html查阅。





在图表 Java字节码类文件格式结构中最不容易理解但最重要的是静态池,我们可以把静态池理解为在图表 冯•诺伊曼存储程式结构中提到的扁平线性地址编码的一种方法(基本每一种可知行文件格式都有静态池的概念)。静态池是一个类的结构索引,其它地方对“对象”的引用可以通过索引位置来代替,我们知道在程序中一个变量可以不断地被调用,要快速获取这个变量常用的方法就是通过索引变量。这种索引我们可以直观理解为“内存地址的虚拟”。我们把它叫静态池的意思就是说这里维护着经过编译“梳理”之后的相对固定的数据索引,它是站在整个JVM(进程)层面的共享池。





其次容易混淆的是图表 Java字节码类文件格式结构中的元数据(英文单词Filed和Attribute翻译有点让人迷惑)概念。元数据是一个给类添加额外说明信息的地方,例如把某类标识为作废等信息,在Java 5中提出的元数据(Metadata)都存储在这个结构中。





大家好奇的是到目前为止我们还没有看到指令在那里(应该在方法中吧?的确如此)。我们无论写任何程序,通常用方法(Method)来做某一件事情,通过嵌套或逐个调用方法来完成一系列的事情,例如C语言从main方法开始执行,Java也从main方法开始执行等。那么指令一定在方法中(当然在Java中还有静态执行块的概念,但也以一个类的构造方法来对待,即也在方法范畴)。





那么我们先看看方法在Java字节码类文件中的结构(从图表 Java字节码类文件格式结构的方法中“引用”如下结构):






java字节码文件的后缀名称 java字节码文件的扩展名_java_03





方法在Java字节码类文件中的结构






java字节码文件的后缀名称 java字节码文件的扩展名_平台_04





Java字节码类文件方法结构中代码的结构





好,对Java字节码类文件(.class)的格式就介绍到这里。具体细节请阅读该章的 参考资料部分。





为了让大家深入理解基于Java字节码的应用,大家可以研究如下Java字节码的开源库(这些开源库都是在充分理解Java字节码类文件格式的基础上编写的):