美文网首页
《深入理解JVM虚拟机》 - 类文件结构

《深入理解JVM虚拟机》 - 类文件结构

作者: 陈菲TW | 来源:发表于2020-02-25 17:01 被阅读0次

类文件也就是class文件,是java文件编译后的结果,每个类、接口对应一个class文件。但其实除了java,JVM还支持多种语言,虚拟机只和class文件绑定。不同语言通过各自编译器编译为类文件,交给虚拟机执行;java有javac编译器,groovy有groovyc编译器。class文件中为字节码,字节码的语义表述能力大于java,这也是其他语言有别于java的基础。

虚拟机的平台无关性:平台指硬件平台,虚拟机实现语言与平台的隔离,语言无需考虑平台,只需编译生成虚拟机可读的类文件;然后虚拟机负责把类文件的字节码转化为平台可执行的二进制。因此java的编译结果是类文件中的字节码;c/c++编译结果是二进制,与硬件平台(intel x86指令集)/操作系统强相关。

类文件的结构

java代码 -- javac编译器 -- 类文件 -- jvm执行引擎。

类文件是以字节为单位的二进制流,又成为字节码,按高位在前的顺序排列,无分隔符。两种数据类型:无符号数和表;用u1/u2/u4/u8表示n个字节的无符号数;表%s_info表示复合数据结构;计数器%s_count + 若干数据项表示数据集合。类文件字节码分析工具:Oracle的javap

1. 类文件构成

1)magic(u4):类文件的头四个字节称为magic number,用于确定该类文件是否能被虚拟机接受,值固定为‘0xCAFEBABE’

2)minor/major version(u2):类文件的主/次版本号,如45.3表示主/次版本号分别是45/3。虚拟机向下兼容,拒绝执行超过其版本号的类文件。50/51/52是javac内部版本,对应java6/7/8等。报错:Unsupported major.minor version 50.0。

3)constant pool(cp_info列表)常量池/常量列表,包含计数器和具体常量列表。

计数器:从1开始,22代表有21个常量,index是1~21;0表示不引用任何常量池项目。

用于存放:1. 字面量literal(类似java的final常量);2. 符号引用(编译原理)类/接口的全限定名,字段/方法的名称/描述符;3. 字段/方法/属性表中会引用到的长度不固定的内容。类文件只包含符号引用,不含直接引用(内存地址),虚拟机在类加载的解析阶段把符号引用并映射到内存地址。

常量池支持14种常量表结构,开头的1字节标识位指示所属类型。Utf8_info, Integer_info, Float_info, Long_info, Double_info, String_info;class_info, Fieldref_info, Methodref_info, InterfaceMethodref_info, NameAndType_info, MethodHandle_info, MethodType_info, InvokeDynamic_info。其中utf8_info用于表示类/方法/字段名称。

4)access flags(u2):用于标志类是接口/类/注解/枚举,是否是public/abstract/final。

5)类/父类/接口索引:确定类的继承关系。类索引(u2):类的全限定名-->常量池中的CONSTANT_Class_info-->CONSTANT_Utf8_info中的全限定名;父类索引(u2):父类的全限定名;接口索引列表(u2):实现了哪些接口

6)字段列表(field_info):存储类变量与实例变量,不包含父类字段。字段信息包括:作用域(public/protected/private)static/final/volatile/transient,字段数据类型,字段名称。各个修饰符用布尔值表示,字段数据类型和字段名用常量池中的常量描述。对象数据类型用L加全限定名表示。数组每一维度用[描述,比如String数组:[Ljava/lang/String;

7)方法列表(method_info):方法数据包含访问标记(boolean表示);方法名,参数/返回值数据类型(常量池表示);属性表集合,如方法体编译后的字节码放在属性表‘Code’。把java类分为代码和元数据,class文件中只有code属性描述代码,其他都是元数据描述。

8)属性列表(attribute_info):具有可扩展性,虚拟机规范预定义了以下属性:1.Code存储方法的代码实现字节码,是最重要的属性;2. exceptions:方法签名上的异常;3. lineNumberTable:java源码行号与字节码行号对应关系,用于异常堆栈打印行号/程序断点调试。属性名称引用在常量池。

2. 字节码指令简介

字节码指令:每个指令是u1的单字节操作码,虚拟机读到字节码时,查看虚拟机字节码指令表,找到其对应指令/指令是否需要参数(操作数)/参数如何解析。单字节可以表示256条指令,目前已经定义200条。

类文件格式没有采用编译后代码的操作数长度对齐,好处是省略填充和间隔符号;坏处是虚拟机处理16位长度的数据时,需要从字节重建数据结构。

常见指令:1. 加载和存储指令,用于将数据在栈帧中的局部变量表和操作数栈之间传递:load/store;2. 运算指令:add/inc/sub等;3. 类型转换指令:java虚拟机自动支持宽化类型转换;4. 对象创建与访问指令:new,get;5. 操作数栈的管理指令:pop,dup,swap;6. 控制转移指令:条件,goto;7. 方法调用与返回:invoke,invokedynamic,return

3. 共有设计与私有实现

概念模型与实际执行过程外部看起来等效,内部实现可以不同。

相关文章

网友评论

      本文标题:《深入理解JVM虚拟机》 - 类文件结构

      本文链接:https://www.haomeiwen.com/subject/nwytchtx.html