Java类文件结构


实现余元无关性基础仍然是虚拟机与字节码储存格式。Java虚拟机不和包括Java在内的任何语言绑定,只与‘Class’文件这种特定的二进制文件格式进行关联,任何其他语言的实现者都可以将Java虚拟机作为语言的交付媒介,例如JRuby等其它语言编辑器一样可以将程序代码翻译成Class文件。

Class类文件结构

Class文件的一组8字节为基础单位的二进制流,各个数据项目按照顺序严格紧凑的排列在Class文件中,中间没有任何分隔符,其中储存的数据全是程序运行的必要数据。

Class文件采用一种类似于C语言的伪结构体来储存数据,这种伪结构中有两种数据类型:无符号数、表。

  • 无符号数
    属于基本数据类型,以u1、u2、u4、u8分别代表1、2、4、8字节的无符号数,无符号数可以用来描述数字、索引引用、数量值、按照UTF-8编码构成字符串值。


  • 由多个无符号数或者其他数据项构成的复合数据类型,所有表都习惯以‘_info’结尾。

Class文件结构
无论是无符号数还是表,当描述同一类型但数量不定的多个数据时,经常会使用一个前置的容量计数器加若干连续的数据项的形式,这时称这一系列连续的某一类型的数据为某一类型的集合。

魔数与Class文件版本

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

不使用扩展名进行身份识别是处于安全性考虑,因为扩展名可以被更改。

紧接着魔数的4个字节储存的是Class文件的版本号,第5、6个字节表示次版本号,第7、8个字节表示主版本号。如图下蓝色标记的表示次版本号,紫色标记的表示主版本号
在这里插入图片描述

常量池

紧接着主次版本号之后的是常量池的入口,由于常量池中的常量的数量不是固定的,因此在常量池的入口需要放置一项u2类型的数据,表示常量池容量计数器值。容量计数器从1开始而不是0。图上用红色标记十进制表示为24,代表常量池中有23个常量,索引范围是1~23,第0项常量用来表示不引用任何一个常量池项目。

常量池中主要存放两大类常量:字面量、符号引用。

  • 字面量
    接近Java层面语言的常量概念,如文本字符串、final常量值等

  • 符号引用
    包括三类常量:类和接口的全限定名、字段名称与描述符、方法名称与描述符
    常量池项目类型

访问标志

在常量池结束之后,紧接着的两个字节代表访问标志,这个标志用于标识一些类或接口层次的信息,包括:这个Class是类还是接口,是否为public类型,是否定义为abstract类型等。
访问标志

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

类索引、父类索引都是一个u2类型的数据,接口索引集合u2类型的集合,Class文件由着三项数据确定类的继承关系。类索引用于确定类的全限定名,父类索引用于确定类的父类的全限定名,被实现的接口将按照implements语句后的顺序从左到右排列在接口索引集合中。

字段表集合

字段白哦集合用于描述接口或类中声明的变量。字段包括类即变量以及实例级变量,但不包括方法内部声明的局部变量。
字段表结构
(图片来自百度图片)

字段修饰符放在access_flags项目中,其中可以设置的标志参考‘访问标志’一栏。有关name_index,descriptor_index都是对于常量池的引用,分别代表字段的简单名称以及字段和方法的描述符。

方法表集合

其结构与字段表集合一样,这里不多做赘述。

所有数据项目的含义仅在访问标志和属性表集合的可选项中有所区别。由于volatile和transient关键字不能修饰方法,所以方法表的访问标志没有了ACC_VOLATILE和ACC_TRANSIENT标志。

与字段表集合对应,如果父类方法在子类方法中没有被重写(override),方法表集合中不会出现来自父类的方法信息。

属性表集合

在Class文件、字段表、方法表都可以携带自己的属性表集合,用于描述某些场景专有的信息。
属性表集合不在要求各个属性表具有严格的顺序,只要不予属性名重复,任何人实现的编译器都可以向属性表中写入自己定义的属性信息,Java虚拟机运行时会自动忽略不认识的属性信息。在这里插入图片描述

  • code属性
    Java程序方法体重的代码经过javac编译器处理后,最终变成字节码指令存储在code属性中。并非所有方法都必须存在这个属性,比如接口与抽象类中的方法就不存在code属性。
    code属性结构表

  • Exception属性
    这里的exception属性与code属性平级,作用是列举方法中可能抛出的受查异常,也就是throws关键字后面列举的异常

  • LineNumberTable属性
    用于描述Java源码行号与字节码行号对应关系,不是运行时必须属性,但默认会生成到Class文件中

  • LocalVariableTable属性
    用于描述栈帧中局部变量表中的变量与java源码定义的变量之间的关系,也不是运行时必须属性

  • SourceFile属性
    用于记录生成这个Class文件的源码文件名称

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值