Java虚拟机(二)—class结构

类文件结构

类文件是一组以8位字节为基础的二进制流,各个数据必须严格按照顺序排列在类文件中,并且只有两种数据类型

  • 无符号数: 描述数字、索引引用、数量值或者UTF-8编码的字符串
  • 表: 由无符号数或其它表作为数据结构的符合数据类型
名称 类型 数量
magic u4 1
minor_version u2 1
major_version u2 1
constant_pool_count u2 1
constant_pool cp_info constant_pool_count-1
access_flag u2 1
this_class u2 1
super_class u2 1
interfaces_count u2 1
interfaces u2 1
fields_count u2 1
field_info fields fields_count
methods_count u2 1
methods methods_info methods_count
atrributes_count u2 1
atrributes atrribute_info atrributes_count

魔数和class文件版本

每个class文件头4个字节称为魔数(magic),用于确定这个class文件是否能被虚拟机接受,class文件魔数为0xCAFEBABE。

紧接着魔数后4个字节是class文件版本号,第5和第6字节是次版本号(minor_version),第7和第8字节是主版本号(major_version)

常量池

主版本号之后是常量池入口,常量池是class文件结构中与与其它数据关联最多的数据类型。常量池入口有一个u2类型的数据,代表常量池容量计数(constant_pool_count),这个值从1开始,0有特殊作用,表示在特定情况下不引用任何一个常量池项目。

常量池中主要存放一下两种常量

  • 字面量(Literal): 常量,如文本字符串和被声明为final的常量值等
  • 符号引用(Symbolic Reference):
    • 类和接口的全限定名
    • 字段的名称和描述符
    • 方法的名称和描述符

访问标记

常量池之后是访问标记(access_flag),用于识别一些类或接口的访问信息

标记名称 标记值 含义
ACC_PUBLIC 0x0001 是否为public
ACC_FINAL 0x0010 是否为final,只有类可以设置
ACC_SUPER 0x0020 是否允许使用invokespecial字节码指令,JDK 1.2之后为true
ACC_INTERFACE 0x0200 是否为接口
ACC_ABSTRACT 0x0400 是否为abstract类型,接口和抽象类为true,其它为false
ACC_SYNTHETIC 0x1000 非用户代码产生
ACC_ANNOTATION 0x2000 是否为注解
ACC_ENUM 0x4000 是否为枚举

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

  • 类索引(this_class): 用于确定这个类的全限定名
  • 父类索引(super_class)是u2类型: 用于确定这个父类的全限定名
  • 接口索引(interfaces_count): 用来描述这个类实现了哪些接口,是一组u2类型的数据集合

字段表集合

  • 字段表(field_info): 用于描述接口或类中声明的变量
  • 字段(fields): 包含了类级别变量或实例变量,但不包含方法内部声明的变量

字段表结构

名称 类型 数量 说明
access_flags u2 1 访问限定标记
name_index u2 1 对常量池引用,字段的简单名字
descriptor_index u2 1 对常量池引用,字段和方法的描述符
attributes_count u2 1
attributes attributes_info 1

字段访问标志

|ACC_PUBLIC| 0x0001 | 是否为public|
|ACC_PRIVATE| 0x0002 | 是否为private|
|ACC_PROTECTED| 0x0004 | 是否为protected|
|ACC_STATIC| 0x0008| 是否为static|
|ACC_FINAL| 0x0010| 是否为final|
|ACC_VOLATILE| 0x0040| 是否为volitale|
|ACC_TRANSIENT| 0x0080| 是否为transient|
|ACC_SYNTHETIC| 0x1000| 是否由编译器自动产生|
|ACC_ENUM| 0x4000| 是否为枚举|

方法表集合

和字段表集合类似

属性表集合

属性表(attributes_info)用于描述某些场景专有的信息。

名称 使用位置 含义
Code 方法表 Java代码变异成的字节码指令
ConstantValue 字段表 final关键定义的常量
Deprecated 类、方法和字段表 被声明为deprecated的方法和字段
Execeptions 方法表 方法跑出的异常
InnerClass 类方法 内部类列表
LineNumberTable Code属性 Java源码的行号与字节指令的对应关系
LocalVariableTable Code属性 方法的局部变量描述
SourceFile 类文件 源文件名称
Synthetic 类、方法和字段表 表示方法或字段为编译器自动生成
code属性

Java方法体里的代码被编译器处理后最终变成字节码存在code属性内

名称 类型 数量 说明
attribute_name_index u2 1 指向CONSTANT_Utf8_info常量的索引,固定为Code
attribute_length u4 1 属性值的长度
max_stack u2 1 操作栈最大深度,虚拟机运行时需要根据这个值来分配栈帧的栈深度
max_locals u2 1 表示局部变量所需的储存空间,单位是slot,是虚拟机为局部变量分配内存所使用的最小单位(1 slot = 32bit)
code_length u4 1 字节码的长度,虽然是u4,但是字节码长度不能超过65535
code u1 code_length 储存字节码
exception_table_length u2 1
exception_table exception_info 1
attribues_count u2 1
attributes attribute_info attribues_count

Exception属性

用于列举出方法中可能抛出的受查异常

名称 类型 数量 说明
attribute_name_index u2 1
attribute_length u4 1 属性值的长度
number_of_exceptions u2 1
exception_index_table u2 number_of_exceptions

LineNumberTable属性

用于描述Java源代码和字节码行号(偏移量)之间的对应关系,不是运行时必须的属性,如果不生成该属性就无法再抛出异常时返回代码中对应的行号。

名称 类型 数量 说明
attribute_name_index u2 1 属性值的索引
attribute_length u4 1 属性值的长度
line_number_table_Length u2 1
line_number_table line_number_info line_number_table_length

LocalVariableTable属性

用于描述栈帧中局部变量表中的变量与Java源码中定义的变量之间的关系,不是运行时必须的属性,如果没有生成所有参数名称都将丢失

名称 类型 数量 说明
attribute_name_index u2 1 属性值的索引
attribute_length u4 1 属性值的长度
local_variable_table_Length u2 1
local_variable_table local\ _variable_info local_variable_table_length
local_variable_info结构
名称 类型 数量 说明
start_pc u2 1 这个局部变量声明周期开始时的字节码偏移量
length u2 1 这个局部变量声明周期开始时的字节码作用范围的长度
name_index u2 1 指向CONSTANT_Utf8_info常量的索引,代表局部变量的名称
descriptor_index 1 指向CONSTANT_Utf8_info常量的索引,代表局部变量的描述符
index 1 u2 表示这个局部变量在栈帧局部变量中slot的位置

SourceFile属性

用于记录生成这个class文件源代码的名称,是可选的,如果不生成这个属性,抛出异常时不会显示出错代码的文件名。

名称 类型 数量 说明
attribute_name_index u2 1 属性值的索引
attribute_length u4 1 属性值的长度
sourcefule_index u2 1 指向CONSTANT_Utf8_info常量的索引,常量值时源码文件的文件名

ConstantValue属性

ConstantValue属性的作用是通知虚拟机自动为静态变量赋值,只有被static修饰的变量才能用这个属性

名称 类型 数量 说明
attribute_name_index u2 1 属性值的索引
attribute_length u4 1 属性值的长度
constant_value_index u2 1 指向常量池的引用

InnerClasses属性

InnerClasses属性用于记录内部类与宿主类之间的关联,如果一个类中有内部类,则会生成InnerClass属性。

名称 类型 数量 说明
attribute_name_index u2 1 属性值的索引
attribute_length u4 1 属性值的长度
nubmber_of_classes u2 1 代表记录多少个内部类信息
inner_class inner_class_info nubmber_of_classes
inner_class_info
名称 类型 数量 说明
inner_class_info_index u2 1 指向CONSTANT_Class_info常量的索引,代表内部类的符号引用
outter_class_info_index u2 1 指向CONSTANT_Class_info常量的索引,代表宿主类的符号引用
inner_name_index u2 1 指向CONSTANT_Utf8_info常量的索引,代表这个内部类的名称,如果是匿名内部类则为0
inner_name_access_flag u2 1 内部类的访问标志

Deprecated属性

表示某个类、字段或方法不再推荐使用

Synthetic属性

表示该字段和方法是不是有Java源码直接生成的

名称 类型 数量 说明
attribute_name_index u2 1 属性值的索引
attribute_length u4 1 属性值的长度,值必须为0x00000000

参考

  • 深入理解Java虚拟机, 周志明
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容