JVM- 技术专题 -Java 类文件结构

用户头像
李博@Alex
关注
发布于: 2020 年 10 月 12 日
JVM-技术专题-Java类文件结构

一、Class 类文件的结构

Class 文件是一组以8位字节为基础的二进制流,没有间隙存在,当需要占用8位字节以上空间的数据项时,则会按照高位在前的方式分割成若干个8为字节进行存储。

Class 文件采用与C语言类似的伪结构,这种结构只有两种数据:无符号和表

无符号:属于基本类型,如u1,u2、u3、u4和u8来区分1、2、3、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量之或者按照utf-8编码构成的字符串值。

表:是由多个无符号或者其他表作为数据项构成的符合数据类型,所有表都习惯用“_info”结尾 ,用于描述有层次关系的符合结构的数据,如字段表、方法表、属性表等,整个Class文件本质上就是一张表。

无论是无符号还是表,当需要描述同一类型但数量不定的多个数据时,会使用一个前置的容量计数器+若干个连续的数据项的形式,这一类型我们叫做集合。

二、魔数与Class版本号

每个Class文件的前4个字节成为魔数,它的唯一作为就是标明这个Class能不能被虚拟机结构。魔数的值为 OXCAFEBABE (咖啡宝贝),还是挺好记的,然后第5,第6个字节,表示此版本号,第7,第8则表示次版本号。如(图片来自深入Java虚拟机第2版):



三、常量池

从上面看,从第9位开始就是常量池了,常量池可以理解为 Class 文件之中的资源仓库,它是 Class 文件结构中与其他项目关联最多的数据类型,也是占 Class 文件控件最大的数据项目之一。不过,常量池的数量是不固定的,所以在入口设置了一项u2类型的数据,代表常量池容量计数值。这个计算值是从1开始的,这是为了满足后面某些指向常量池的索引值的数据在特定情况下需要表达“不引用任何一个常量池项目”的意义。

常量池中主要存放两大类型,字面量和符号引用;字面量是Java语言层面的常量概念,符号引用是编译原理方面的概念 ,如下图:

字面量比较好理解,符号引用怎么解释呢?原因是 Java 不想C/C++有"连接"这一步骤, Java是动态语言,是在虚拟机加载 Class 文件的时候,动态连接的;也就是说, Class 文件不会保存各个方法、字段的最终内存信息,如果不经过转换,则得不到真正的内存入口,也就没办法在虚拟机引用了。所以,当虚拟机运行时,需要从常量池中获取对应的符号引用,再在创建类时或运行时,解析得到真正的内存寻址。

类索引、父类索引与接口索引集合

类索引和父类索引都是一个 u2 类型的数据,而接口索引集合则是一个 u2 类型的数据集合。

类索引:用来确定这个类的全限定名

父类索引:用来确定父类全限定名,Java不允许多继承,所以只有一个

接口索引集合:用来确定这个类实现了哪些接口

总结:class文件中存储的具体信息格式不需要很清楚,但是我们要明白,class文件数据的存储顺序比如按照虚拟机规范的严格格式(前4个字节时魔数,接下来4个字节存放版本号,等等顺序,大小必须正确),否则在运行时无法正确加载。

还有一个class文件对应唯一的一个类或接口的定义信息,我们可以在一个java文件中写2个类或者接口(内部类不算)但是编译出来的class文件等于所有class加上interface。

深入Java虚拟机之类文件结构

深入理解java虚拟机(3)-----字节码文件格式和类加载

用户头像

李博@Alex

关注

我们始于迷惘,终于更高的迷惘. 2020.03.25 加入

一个酷爱计算机技术、健身运动、悬疑推理的极客狂人,大力推荐安利Java官方文档:https://docs.oracle.com/javase/specs/index.html

评论

发布
暂无评论
JVM-技术专题-Java类文件结构