jvm类文件结构
2022-01-06 15:37:06 0 举报
AI智能生成
总结至《深入理解java虚拟机 3》
作者其他创作
大纲/内容
以8个字节为基础单位的二进制流,紧密排列没得间隔符
无符号数
以u1、 u2、 u4、 u8来分别代表1个字节、 2个字节、 4个字节和8个字节的无符号数, 无符号数可以用来描述数字、 索引引用、 数量值或者按照UTF-8编码构成字符串值
基本数据类型
表
表是由多个无符号数或者其他表作为数据项构成的复合数据类型
class表
头4字节,魔数
0xCAFEBABE(咖啡宝贝? ),标识class文件
第1、2、3、4字节
minor version
第5、6字节,次版本号
major version
第7、8字节,主版本号
constant_pool_count
第9、10字节
常量池计数值
常量池入口
表类型数据
常量池容量从1开始算
存放:字面量
几乎于java中的常量,文本字符串、final声明的等
存放:符号引用
编译方面的常量
被模块导出或者开放的包(Package)
类和接口的全限定名(Fully Qualified Name)
字段的名称和描述符(Descriptor)
方法的名称和描述符
方法句柄和方法类型(Method Handle、 Method Type、 Invoke Dynamic)
动态调用点和动态常量(Dynamically-Computed Call Site、 Dynamically-Computed Constant)
虚拟机进行类加载的时候利用这些字段、方法的符号引用找到对应的内存地址
常量池中每一项也是表
最初有11种表结构,jdk13增加至17种
每种表都有自己的结构,但第1个字节都表示其相应的tag
表6-3
java中字段、方法名由CONSTANT_Utf8_info常量结构定义,其length定义是u2,因此最长的字段、方法名为64kB
access_flags
常量池结束后的1、2字节
代表访问标志
用于识别一些类或者接口层次的访问信息,如类或者接口的声明情况,public (final) (abstract) class
总共16个标志位(2字节),目前使用9个
子主题
this_class\super_class\interfaces
类、父类、接口集合 索引
类索引和父类索引用两个u2类型的索引值表示, 它们各自指向一个类型为CONSTANT_Class_info的类描述符常量,CONSTANT_Class_info里面又有指向常量项的索引,这个常量又指向UTF8常量,从而那大类全限定名
子主题
接口,开始为接口计数,个数描述了后面有多少接口索引,如果个数为0,后面就不占用字节
field_info
字段表用于描述接口或者类中声明的变量
子主题
acess_flags
name_index
指向常量池项,表示字段简单名称。
简单名称则就是指没有类型和参数修饰的方法或者字段名称
descriptor_index
也是指向常量池项,该项用来描述字段的数据类型、 方法的参数列表(包括数量、 类型以及顺序) 和返回值
attribute_info
存储一些额外的信息, 字段表可以在属性表中附加描述零至多项的额外信息
java中, 两个字段的数据类型、 修饰符不管是否相同, 都必须使用不一样的名称, 但是对于Class文件格式来讲, 只要两个字段的描述符不是完全相同, 那字段重名就是合法的。
method_info
方法表,描述方法,基本结构类似字段表
子主题
方法代码存在属性表中的Code里面
子类没有重写父类方法,则不会出现继承的方法信息
java中方法重载必须特征签名不同
特征签名:特征签名是指一个方法中各个参数在常量池中的字段符号引用的集合, 也正是因为返回值不会包含在特征签名之中, 所以Java语言里面是无法仅仅依靠返回值的不同来对一个已有方法进行重载的。
class 文件中两个方法的描述符不同便可以重载
attribute_info
子主题
attribute_name_index
它的名称都要从常量池中引用一个CONSTANT_Utf8_info类型的常量来表示
Code属性表
子主题
attribute_name_index
CONSTANT_Utf8_info型常量的索引, 此常量值固定为“Code”
max_stack
操作数栈(Operand Stack) 深度的最大值,虚拟机根据此来分配栈帧
max_locals
代表了局部变量表所需的存储空间
变量槽为局部变量分配的最小内存单位,64位类型数据占2个,其他1个
变量槽可以根据代码作用域重用
code
存储字节码指令
一个字节代表一个指令,已经定义了200左右个指令
可查虚拟机字节码指令表
code_length
字节码指令长度
最长65535个
exception_info
字节码指令异常跳转逻辑
Exception属性
列举出方法中可能抛出的受查异常(Checked Excepitons) , 也就是方法描述时在throws关键字后面列举的异常。
子主题
LineNumberTable属性
LineNumberTable属性用于描述Java源码行号与字节码行号(字节码的偏移量) 之间的对应关系
如果javac排除此属性,当抛出异常时, 堆栈中将不会显示出错的行号, 并且在调试程序的时候, 也无法按照源码行来设置断点
LocalVariableTable属性
栈帧中局部变量表的变量与Java源码中定义的变量之间的关系,运行时非必须
编译去掉时,最大的影响就是当其他人引用这个方法时, 所有的参数名称都将会丢失, 譬如IDE将会使用诸如arg0、 arg1之类的占位符代替原有的参数名
SourceFile属性
非必须
用于记录生成这个Class文件的源码文件名称,如果不生成这项属性, 当抛出异常时, 堆栈中将不会显示出错代码所属的文件名。
ConstantValue属性
通知虚拟机自动为静态变量赋值
如果同时使用final和static来修饰一个变量 , 并且这个变量的数据类型是基本类型或者java.lang.String的话, 就将会生成ConstantValue属性来进行初始化
子主题
constantvalue_index指向常量池的索引
CONSTANT_Long_info、 CONSTANT_Float_info、 CONSTANT_Double_info、
CONSTANT_Integer_info和CONSTANT_String_info
CONSTANT_Integer_info和CONSTANT_String_info
InnerClasses属性
属性用于记录内部类与宿主类之间的关联
Deprecated及Synthetic属性
都属于标志类型的布尔属
Deprecated表示类、方法、字段被弃用
Synthetic属性代表此字段或者方法并不是由Java源码直接产生的, 而是由编译器自行添加
最典型的例子就是枚举类中自动生成的枚举元素数组和嵌套类的桥接方法(Bridge Method)
StackMapTable属性
code属性中用于字节码验证
Signature属性
用于记录泛型签名信息
BootstrapMethods属性
保存invokedynamic指令引用的引导方法限定符
MethodParameters属性
jdk8引入
记录方法的各个形参名称和信息
模块化相关属性
jdk9
源码
class 文件实例图 6-3
子主题
0 条评论
下一页