JVM学习-Class文件结构

我们一直在学习Java语法和Java虚拟机,Java是高级面向对象语言,但是在Java虚拟机中执行的是二进制机器码,两者之间是否存在一种中间码?在c语言中,程序员编写的代码直接由编译器生成机器码执行,这样虽然提高了效率,但是在不同的平台之间这种方法显然不是通用的,因为在不同的平台中指令集显然是不同的。比起C/C++,Java是可以跨平台的,一句有名的Java广告语这么说“Write Once,Run Anywhere”,那么Java的跨平台是如何实现的。奥妙就在Java语言在高级语言和机制码之间存在一种字节码作为过度,这种字节码屏蔽了机器实现的细节,它就是本文需要讨论的Class文件(类文件);

JVM与Class文件

JVM其实是不和任何语言绑定的,如今很多语言也能够在JVM上面运行,如Clojure、Groov、JRuby、Jython、Scala等。Java虚拟机只与特定的二进制文件格式(Class文件)相关联,Class文件包含了JVM指令集以及若干其他辅助信息。上述可以这么理解,JVM并不关心Class文件的来源是何种语言,用其他语言编写的程序只要能编译为Class文件,JVM就能解释执行。

Class文件

Class文件是一组以8位字节为基础单位的二进制流,各个数据项严格按照顺序紧凑地排列在Class文件中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。

Class文件采用一种类似于C语言的结构体来存储数据,它只有两种数据类型:无符号数和表。表是一种复合数据结构,它是由无符号数或者表作为数据项的。下面我们来看看Class文件中究竟有哪些数据项:

  • 魔数与Class文件的版本号。每个Class文件的头4个字节称为模数,它的唯一作用是确定这个文件是否为一个能被虚拟机接受的Class文件,它的值为:0xCAFEBABE。接下来的四个字节是Java的版本号。

  • 常量池。它是Class文件的资源仓库,其中主要存放两大类常量:字面量和符号引用。字面量包括文本字符串和声明为Final的常量值等,符号引用包括:类和接口的全限定名,字段的名称和描述符,方法的名称和描述符。常量池中每一项都是一个表,它也是最繁琐的数据项。

  • 访问标志。常量池结束后的两个字节代表访问标志,它包括:这个Class是类还是接口;是否定义为public类型;是否定义为abstract类型;如果是类是否被声明为final。

  • 类索引、父类索引与接口索引。这些索引用于描述这个类的属性,他们分别指向自身,父类及它继承的接口。

  • 字段表集合。用于描述接口或是类中声明的变量。

  • 方法表集合。顾名思义,就是接口或者类中定义的方法。

  • 属性表集合。前面的表可以携带自己的属性集合,以用于描述某些场景专有的信息。如方法表中就带有Code属性,它是用来存储Java源程序编译后生成的字节码指令。

后记

Javac编译而成的Class文件将程序员编写的高级语言转化成为了JVM认识的字节码,它包含了JVM运行程序需要的属性值和code指令码,接下来的事情就是JVM来将它们转化为机器码,并执行出结果了。



Previous     Next
zhing /
Published under (CC) BY-NC-SA in categories java  tagged with java