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

1、Class类文件的结构

class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑的排列在class文件中,中间没有添加任何分隔符。当遇到需要占用8位字节以上空间的数据项时,则按照高位在前的方式分割成若干个8位字节存储。

class文件格式只有两种数据类型:无符号数和表。

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

表是由多个无符号数或其他表作为数据项构成的复合数据类型,以"_info"结尾,整个class文件就是一张表:

Class文件格式

1.1 魔数与Class文件版本

(1) Class文件的魔数值是:0XCAFEBABE(音译:咖啡宝贝)

(2) 紧接着魔数的4个字节是版本号,第5和第6个字节是次版本号(Minor Version),第7和第8是主版本号(Major Version)

1.2 常量池

(1) 版本号之后是常量池入口,常量池是Class文件中的资源仓库

(2) 常量池入口放置的是constant_pool_count,计数从1开始,第0项常量表示“不引用任何一个常量池项目”

(3) 常量池存放两大类常量:字面量(Literal)和符号引用(Symbolic Reference),字面量包括文本字符串、声明为final的常量值等,而符号引用包括3类:类和接口的全限定名、字段的名称和描述符,方法的名称和描述符,共有14种结构不同的表数据:

常量池的项目类型

(4) 专门用于分析Class文件字节码的工具:javap

1.3 访问标志

在常量池之后,紧接着的两个字节是访问标志(access_flags),用于标识类或接口的访问信息,含义见下表:

访问标志

1.4 类索引、父类索引和接口索引

类索引(this_class)和父类索引(super_class)都是一个u2类型的数据,而接口索引集合(interfaces)是一组u2类型数据的集合,Class文件中由这三项数据来确定这个类的继承关系。查找过程:常量池索引值 -- CONSTANT_Class_info -- CONSTANT_Utf8_info :

1.5 字段表集合

字段表(field_info)用于描述接口或类中声明的变量,包括类级变量(含static关键字)和实例级字段,不包括方法类的局部变量。字段表结构如下:

字段表结构

access_flags如下图:

name_index和descriptor_index都是对常量池的引用,分别代表字段的简单名称和字段的描述符。描述符用来描述字段的数据类型,标识字符含义如下:

描述符标识字符含义

对于数组类型,每一维度使用前置"["表示,如String[][]将被记录为[[Ljava/lang/String,int[]表示[I

1.6 方法表集合

方法表含义

其中name_index(简单名称)代表没有类型和参数修饰的方法,descriptor_index(描述符)用来描述方法的参数列表(包括数量、类型和顺序)和返回值

方法访问标志

方法中的代码存放在"Code"属性表里,编译器自动添加的方法:类构造器<clinit>方法和实例构造器<init>方法

1.7 属性表集合

详见:https://www.cnblogs.com/flyingcr/p/10428285.html

2、字节码指令简介

字节码指令由一个字节长度,代表着某种特定操作含义的数字(操作码,Opcode),以及其后0至多个此操作所需参数(操作数,Operands)构成

2.1 字节码与数据类型

大多数的指令包含了其操作所对应的数据类型信息,如iload指令用于从局部变量表加载int型数据到操作数栈,而fload用于加载float型数据。助记符与数据类型对代应关系:i代表int,l代表long,s代表short,b代表byte,c代表char,f代表float,d代表double,a代表reference。

2.2 加载和存储指令

加载和存储指令用于将数据在栈帧中的局部变量表和操作数栈之间来回传输。load代表将局部变量加载到操作数栈,store将一个数值从操作数栈存储到局部变量表,push和const代表将常量加载到操作数栈

2.3 运算指令

加法指令:iadd ladd fadd dadd

减法指令:isub lsub fsub dsub

乘法指令:imul lmul fmul dmul

除法指令:idiv ldiv fdiv ddiv

求余指令:irem lrem frem drem

取反指令:ineg lneg fneg dneg

位移指令:ishl ishr iushrl shl lshr lushr

按位或指令:ior lor

按位与指令:iand land

按位异或指令:ixor lxor

局部变量自增指令:iinc

比较指令:dcmpg dcmpl fcmpg fcmpl lcmp

2.4 类型转化指令

窄化类型转化时,需显示的使用转化指令:i2b、i2c、i2s、l2i、f2i、f2l、d2i、d2l和d2f

2.5 对象创建和访问指令

创建类实例的指令:new

创建数组的指令:newarray(基本类型数组)、anewarray(引用类型数组)、multianewarray(多维度引用类型数组)

访问类字段的指令:getstatic、putstatic

访问实例字段的指令:getfield、putfield

将数组加载到操作数栈的指令:aload

将操作数栈的值存储到数组元素的指令:astore

取数组元素长度的指令:arraylength

检查实例类型的指令:instanceof、checkcast

2.6 操作数栈管理指令

pop:栈顶一个元素出栈,pop2:栈顶两个元素出栈

dup:复制栈顶一个数值并将复制值重新压入栈顶,dup2:复制栈顶两个数值并将双份复制值重新压入栈顶

swap:将栈顶的两个数值互换

2.7 控制转移指令

分支条件
switch分支
无条件分支

2.8 方法调用和返回指令

invokevirtual:用于调用对象的实例方法,根据对象的实际类型进行分派

invokeinterface:用于调用接口方法,找到实现该接口合适的类的方法

invokespecial:用于调用实例初始化方法、私有方法和父类方法

invokestatic:用于调用static方法

invokedynamic:用于在运行时动态解析出调用点限定符所引用的方法,并执行该方法

2.9 异常处理指令

显示抛出异常的操作(throw语句)都由athrow指令实现

2.10 同步指令

Java虚拟机支持方法级和方法内部一段指令序列的同步,这两种同步结构都是使用管程(Monitor)来支持的。

方法级的同步是隐式,则无需通过字节码指令来控制,它实现在方法调用和返回操作之中。虚拟机可以从方法常量池的方法表结构中的ACC_SYNCHRONIZED访问标志区分一个方法是否是同步方法。当方法调用时,调用指令将会检查方法的ACC_SYNCHRONIZED访问标志是否被设置,如果设置了,执行线程先持有管程,然后再执行方法,最后在方法完成(无论是正常完成还是非正常完成)时释放管程。在方法执行期间,执行线程持有了管程,其他线程都无法再获得同一个管程。如果一个同步方法执行期间抛出了异常,并且在方法内部无法处理异常,那这个同步方法所持有的管程将在异常抛到同步方法之外时自动释放。

同步指令由synchronized块来表示的,Java虚拟机的指令集中有monitorenter和monitorexit两条指令来支持synchronized关键字的语义,正确实现synchronized关键字需要编译器与Java虚拟机两者协作支持。

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

推荐阅读更多精彩内容