JVM_12_Class文件结构

类文件结构


参考资料:

《Java Class文件结构解析 及 实例分析验证》


还记得那个小故事嘛?在看这个之前,你可以回顾下《JVM_0.5_小故事》

学习了解Class文件的数据结构是了解虚拟机的重要基础之一。

这方面的学习会比较枯燥,so,来吧...


Class文件是JVM执行引擎的入口,也是Java技术体系的基础构成之一;

了解Class文件的结构对后面进一步了解JVM执行引擎有很重要的意义;


说在前面,这小节了解就好..不用过于深究..挑重点看看..



Class文件概述

两种常见的程序编译存储文件格式分类:

1. 编译成"0,1,0,1...."二进制格式的存储机器码文件格式,直接运行在操作系统上。

2. 编译成与操作系统和机器指令集无关的格式作为存储文件格式,运行在隔离硬件平台的虚拟机之上。

C/C++ 编译出来的程序属于第一种,而Class文件属于第二种;


什么是Class文件?

Class文件是经过前端编译(例如Javac编译)后生成的文件(以.class为后缀),一个Class文件对应一个类或一个接口。

Class文件存储的内容称为字节码(ByteCode),包含了JVM指令集和符号表以及若干其他辅助信息。


JVM规范定义了Class文件结构格式,每种JVM实现必须满足规范定义,这样JVM实例才能加载Class文件,运行字节码内容。

但JVM的实现可以在JVM规范的约束下对具体实现做出修改和优化。

从数据类型来看,Class文件是一组以8位字节(8-bit bytes)为基础的二进制字节流构成,8位以上的数据以大端(Big-Endian)高位在前的顺序进行存储,中间没有添加任何分隔符。

从文件形式来看,JVM加载的Class文件不一定来自磁盘,还可能来自网络数据,甚至在运行时直接编译代码字符串生成。



Class文件的作用(优点)是什么?


JVM规范定义Class文件格式来存储字节码,是虚拟机实现 平台无关性、语言无关性的关键


平台无关性

Java语言有"一次编写,到处运行(Write Once , Run Anywhere)"特性。

通过针对不同平台实现的虚拟机作为字节码执行引擎,它在多种操作系统和架构上提供Java运行时环境。


语言无关性

虚拟机只与字节码关联,不与任何语言绑定。

字节码和虚拟机也是语言无关性的基础,因为不止Java语言程序可以编译生成字节码,

其他的很多语言也可以通过相应的编译器编译成JVM规范规定的字节码格式。

目前JDK7和JDK8的JVM已经可以支持一些其他语言运行了,如Croovy、JRuby、Jython、Scala等。



Class文件结构相关定义说明

Class文件的结构是怎样的?

Class文件结构根据《Java虚拟机规范》定义的结构进行存储,类似于C语言的结构体的伪结构。

伪结构中各个数据都有相应的含义,并且各个数据项必须严格按规定的先后顺序排序,他们之间没有信任分隔符和空隙。

所以,存储的几乎都是运行需要的数据(和指令),结构以及说明如下:


类型

名称

数量

说明

u4 

magic 

1 

魔数:确定一个文件是否是Class文件

u2

minor_version 

1 

Class文件的次版本号

u2

major_version 

1 

Class文件的主版本号:一个JVM实例只能支持特定范围内版本号的Class文件(可以向下兼容)。

u2

constant_pool_count 

1 

常量表数量

cp_info 

constant_pool 

constant_pool_count-1

常量池:以理解为Class文件的资源仓库,后面的其他数据项可以引用常量池内容。

u2

access_flags 

1 

类的访问标志信息:用于表示这个类或者接口的访问权限及基础属性。

u2

this_class 

1 

指向当前类的常量索引:用来确定这个类的的全限定名。

u2

super_class

1 

指向父类的常量的索引:用来确定这个类的父类的全限定名。

u2

interfaces_count

1 

接口的数量

u2

interfaces

interfaces_count

指向接口的常量索引:用来描述这个类实现了哪些接口。

u2

fields_count

1 

字段表数量

field_info 

fields 

fields_count

字段表集合:描述当前类或接口声明的所有字段。

u2

methods_count

1 

方法表数量

method_info

methods 

methods_count

方法表集合:只描述当前类或接口中声明的方法,不包括从父类或父接口继承的方法。

u2

attributes_count

1 

属性表数量

attributes_info

attributes 

attributes_count

属性表集合:用于描述某些场景专有的信息,如字节码的指令信息等等。




Class文件结构的数据类型是什么?
Class文件结构中只有两类数据类型:无符号数和表。

a. 无符号数
无符号数属于基本的数据类型,以u1、u2、u4、u8来表示一个字节、两个字节....的无符号数。
无符号数用来描述数字、索引引用、数量值或UTF-8编码构成的字符串值。

b. 表
表是由多个无符号数或其他表作为数据项 构成的复合数据类型,一般以"_info"结尾;
表用来描述有层次关系的复合结构的数据;
......
了解更多,请查阅原博:《Java Class文件结构解析 及 实例分析验证》



魔数与Class文件的版本

每个Class文件的头4个字节称为魔数,它的唯一作用是确定这个文件是否为一个能被虚拟机接受的Class文件。

使用魔数而不是扩展名来进行文件的识别,是基于安全方面的考虑,因为文件扩展名可以所以更改。



常量池

常量池可以理解为Class文件之中的资源仓库,它是Class文件结构中与其他项目关联最多的数据类型;
也是占用Class文件空间最大的数据项目之一,同时它还是在Class文件中第一个出现的表类型数据项目;

1. 常量池数量计数值
由于常量池中常量的数量是不固定的,所以在常量池的入口需要放置一项u2类型的数据,代表常量池容量计数值。

与Java中语言习惯不一样的是,这个容量计数值是从1而不是0开始。

在Class文件格式规范制定之时,设计者将第0项常量空出来是有特殊考虑的,这样做的目的在于满足后面某些指向常量池的索引值的数据在特定情况下需要表达"不引用任何一个常量池项目"的含义,这种情况就可以把索引值置为0来表示。
Class文件结构中只有常量池的容量计数是从1开始的,对于其他集合类型:接口索引集合、字段表集合、方发表集合等的容量计数都与一般习惯相同,是从0开始的。

2. 常量池
常量池中主要存放两大类常量:字面量和符号引用。
字面量比较接近于Java语言层面的常量概念,如文本字符串、声明为final的常量值等..

而符号引用则属于编译原理方面的概念,包括了下面三类常量:
a. 类和接口的全限定名
b. 字段的名称和描述符
c. 方法的名称和描述符


常量池每一项常量都是一个表;
Class文件不会像C/C++编译后保存各个方法、字段的内存布局信息;
JVM运行时,需要从常量池获得对应的符号引用,在类创建或运行解析、翻译到具体的内存地址中。
所以,常量池可以理解为Class文件的资源仓库,后面的其他数据项可以引用常量池的内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值