class文件结构

来源:互联网 发布:淘宝卖蚕丝被 编辑:程序博客网 时间:2024/06/06 01:26

Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑的排列在Class文件之中,中间没有添加任何分隔符。当遇到需要占用8位字节以上空间的数据项时,则会按高位在前的方式分割成若干个8位字节进行存储。

  Class文件结构中只有2种数据类型:无符号数和表无符号数, 属于基本的数据类型,以u1、u2、u4、u8来分别表示1个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值和UTF-8编码构成的字符串;,是由多个无符号数或其他表作为数据项构成的复合数据类型,所有的表都习惯已"_info"结尾(整个Class文件可以看成是一张表)

Class文件都对应着唯一的类或接口的信息,但类或接口不一定都定义在class文件中,也可以是通过类加载器直接生成。

头4个字节魔数,魔数的唯一作用在于确定这个Class文件是否是Java虚拟机接受的Class文件。如gif和jpeg等在文件头中都存在魔术,使用魔术而不是使用扩展名是基于安全性考虑的——扩展名可以随意被改变。Class文件的魔术值为“0xCAFEBABE”

常量池:

在常量池中主要存放字面量符号引用。字面量比较接近Java语言层面的常量概念,比如文本字符串、声明为final的常量值等。符号引用则主要包括三类常量:类和接口的全限定名,字段的名称和描述符,方法的名称和描述符。

Java在进行javac编译时不像c++那样有连接这一步,而是在jvm加载过程中动态连接的。也就是class文件中不会保存各字段、方法的内存布局信息,这些引用不经过转化就无法获得相应的内存入口地址。所以在jvm运行时,需要从常量池中获取符号引用,再在解析过程中翻译符号引用中的具体内存地址。

符号引用与直接引用:

符号引用是一个字符串,它给出了被引用的内容的名字并且可能会包含一些其他关于这个被引用项的信息——这些信息必须足以唯一的识别一个类、字段、方法。这样,对于其他类的符号引用必须给出类的全名。对于其他类的字段,必须给出类名、字段名以及字段描述符。对于其他类的方法的引用必须给出类名、方法名以及方法的描述符。常量池存在于Class文件中,而Class文件是必须首先通过Java虚拟机的类加载机制加载到内存中(确切的说是方法区这个内存区域,回顾一下,方法区存放的主要是对象的实例,这个Class文件是虚拟机对外接受访问的接口)。符号引用和虚拟机布局无关,符号引用属于常量池中的内容,不是说符号引用的目标已经加载到内存中了。

直接引用可以是直接指向引用目标的指针、相对偏移量或者是一个能够间接定位到目标的句柄。直接引用是和虚拟机的内存布局有关的,同一个符号引用在不同的虚拟机上翻译的直接引用一般是不同的。如果有了直接引用,那么引用的目标必定是存在内存中的

 属性表中的code属性:

 Code属性存在方法表的属性集合中,Java方法体在经过编译后最终变成字节码指令存储在code属性内,但并不是所有的方法表都需要存在这个属性,比如抽象类和接口就没有code属性。