深入理解Java虚拟机 类文件结构总结

计算机只认识0和1 所以我们写的程序需要经编译器翻译成由0和1构成的二进制格式才能由计算机执行

平台无关性
Java虚拟机不和包括Java在内的任何语言绑定 它只与“Class文件”这种特定的二进制文件格式所关联 Class文件中包含了Java虚拟机指令集和符号表以及若干其他辅助信息 基于安全方面的考虑 Java虚拟机规范要求在Class文件中使用许多强制性的语法和结构化约束 但任一门功能性语言都可以表示为一个能被Java虚拟机所接受的有效的Class文件

Class类文件的结构
Class文件是一组以8位字节为基础单位的二进制流 各个数据项目严格按照顺序紧凑地排列在Class文件之中 中间没有添加任何分隔符 这使得整个Class文件中存储的内容几乎全部是程序运行的必要数据 没有空隙存在 当遇到需要占用8位字节以上空间的数据项时 则会按照高位在前的方式分割成若干个8位字节进行存储

魔数与Class文件的版本
每个Class文件的头4个字节称为魔数(Magic Number) 它的唯一作用是确定这个文件是否为一个能被虚拟机接受的Class文件

常量池
紧接着主次版本号之后的是常量池入口 常量池可以理解为Class文件之中的资源仓库 它是Class文件结构中与其他项目关联最多的数据类型 也是占用Class文件空间最大的数据项目之一 同时它还是在Class文件中第一个出现的表类型数据项目

访问标志
在常量池结束之后 紧接着的两个字节代表访问标志(access_flags) 这个标志用于识别一些类或者接口层次的访问信息 包括:这个Class是类还是接口 是否定义为public类型 是否定义为abstract类型 如果是类的话 是否被声明为final等

类索引、父类索引与接口索引集合
类索引(this_class)和父类索引(super_class)都是一个u2类型的数据 而接口索引集合(interfaces)是一组u2类型的数据的集合 Class文件中由这三项数据来确定这个类的继承关系

字段表集合
字段表(field_info)用于描述接口或者类中声明的变量 字段(field)包括类级变量以及实例级变量 但不包括在方法内部声明的局部变量

方法表集合
Class文件存储格式中对方法的描述与对字段的描述几乎采用了完全一致的方式 方法表的结构如同字段表一样 依次包括了访问标志(access_flags) 名称索引(name_index) 描述符索引(descriptor_index) 属性表集合(attributes)几项

属性表集合
在Class文件 字段表 方法表都可以携带自己的属性表集合 以用于描述某些场景专有的信息
1.Code属性
Java程序方法体中的代码经过Javac编译器处理后 最终变为字节码指令存储在Code属性

2.Exceptions属性
Exceptions属性的作用是列举出方法中可能抛出的受查异常(Checked Excepitons) 也就是方法描述时在throws关键字后面列举的异常
3.LineNumberTable属性
LineNumberTable属性用于描述Java源码行号与字节码行号(字节码的偏移量)之间的对应关系
4.LocalVariableTable属性
LocalVariableTable属性用于描述栈帧中局部变量表中的变量与Java源码中定义的变量之
间的关系
5.SourceFile属性
SourceFile属性用于记录生成这个Class文件的源码文件名称
6.ConstantValue属性
ConstantValue属性的作用是通知虚拟机自动为静态变量赋值 只有被static关键字修饰的
变量(类变量)才可以使用这项属性
7.InnerClasses属性
InnerClasses属性用于记录内部类与宿主类之间的关联 如果一个类中定义了内部类 那编译器将会为它以及它所包含的内部类生成InnerClasses属性
8.Deprecated及Synthetic属性
Deprecated和Synthetic两个属性都属于标志类型的布尔属性 只存在有和没有的区别 没有属性值的概念
Deprecated属性用于表示某个类 字段或者方法 已经被程序作者定为不再推荐使用 它可以通过在代码中使用@deprecated注释进行设置
Synthetic属性代表此字段或者方法并不是由Java源码直接产生的 而是由编译器自行添加的
9.StackMapTable属性
这个属性会在虚拟机类加载的字节码验证阶段被新类型检查验证器(Type Checker)使用 目的在于代替以前比较消耗性能的基于数据流分析的类型推导验证器
10.Signature属性
任何类 接口 初始化方法或成员的泛型签名如果包含了类型变量(Type Variables)或参数化类型(Parameterized Types) 则Signature属性会为它记录泛型签名信息
11.BootstrapMethods属性
这个属性用于保存invokedynamic指令引用的引导方法限定符

字节码指令简介
Java虚拟机的指令由一个字节长度的 代表着某种特定操作含义的数字(称为操作码 Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数 Operands)而构成 由于Java虚拟机采用面向操作数栈而不是寄存器的架构 所以大多数的指令都不包含操作数 只有一个操作码

字节码与数据类型
在Java虚拟机的指令集中 大多数的指令都包含了其操作所对应的数据类型信息 例如 iload指令用于从局部变量表中加载int型的数据到操作数栈中 而fload指令加载的则是float类型的数据 这两条指令的操作在虚拟机内部可能会是由同一段代码来实现的 但在Class文件中它们必须拥有各自独立的操作码

加载和存储指令
加载和存储指令用于将数据在栈帧中的局部变量表和操作数栈之间来回传输

运算指令
运算或算术指令用于对两个操作数栈上的值进行某种特定运算 并把结果重新存入到操作栈顶

类型转换指令
类型转换指令可以将两种不同的数值类型进行相互转换 这些转换操作一般用于实现用户代码中的显式类型转换操作 或者用来处理字节码指令集中数据类型相关指令无法与数据类型一一对应的问题

对象创建与访问指令
虽然类实例和数组都是对象 但Java虚拟机对类实例和数组的创建与操作使用了不同的字节码指令 对象创建后 就可以通过对象访问指令获取对象实例或者数组实例中的字段或者数组元素

操作数栈管理指令
如同操作一个普通数据结构中的堆栈那样 Java虚拟机提供了一些用于直接操作操作数栈的指令

控制转移指令
控制转移指令可以让Java虚拟机有条件或无条件地从指定的位置指令而不是控制转移指令的下一条指令继续执行程序 从概念模型上理解 可以认为控制转移指令就是在有条件或无条件地修改PC寄存器的值

方法调用和返回指令
invokevirtual指令用于调用对象的实例方法 根据对象的实际类型进行分派(虚方法分派) 这也是Java语言中最常见的方法分派方式
invokeinterface指令用于调用接口方法 它会在运行时搜索一个实现了这个接口方法的对象 找出适合的方法进行调用
invokespecial指令用于调用一些需要特殊处理的实例方法 包括实例初始化方法 私有方法和父类方法
invokestatic指令用于调用类方法(static方法)
invokedynamic指令用于在运行时动态解析出调用点限定符所引用的方法 并执行该方法 前面4条调用指令的分派逻辑都固化在Java虚拟机内部 而invokedynamic指令的分派逻辑是由用户所设定的引导方法决定的

异常处理指令
在Java程序中显式抛出异常的操作(throw语句)都由athrow指令来实现 除了用throw语句显式抛出异常情况之外 Java虚拟机规范还规定了许多运行时异常会在其他Java虚拟机指令检测到异常状况时自动抛出 而在Java虚拟机中 处理异常(catch语句)不是由字节码指令来实现的(很久之前曾经使用jsr和ret指令来实现 现在已经不用了) 而是采用异常表来完成的

同步指令
Java虚拟机可以支持方法级的同步和方法内部一段指令序列的同步 这两种同步结构都是使用管程(Monitor)来支持的同步一段指令集序列通常是由Java语言中的synchronized语句块来表示的 Java虚拟机的指令集中有monitorenter和monitorexit两条指令来支持synchronized关键字的语义 正确实现synchronized关键字需要Javac编译器与Java虚拟机两者共同协作支持

公有设计和私有实现
Java虚拟机规范描绘了Java虚拟机应有的共同程序存储格式:Class文件格式以及字节码指令集 这些内容与硬件 操作系统及具体的Java虚拟机实现之间是完全独立的 虚拟机实现者可能更愿意把它们看做是程序在各种Java平台实现之间互相安全地交互的手段
虚拟机实现的方式主要有以下两种:
将输入的Java虚拟机代码在加载或执行时翻译成另外一种虚拟机的指令集
将输入的Java虚拟机代码在加载或执行时翻译成宿主机CPU的本地指令集(即JIT代码生
成技术)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值