深入理解java虚拟机读书笔记,第八章:虚拟机字节码执行引擎

8.1概述

执行引擎:输入字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果

8.2运行时栈帧结构

栈帧是虚拟机用于方法调用和方法执行的数据结构,是虚拟机运行时数据区的虚拟机栈的栈元素

栈帧存储了方法的局部变量表、操作数栈、动态连接、方法返回地址等信息

每一个方法从调用开始到执行结束,就是栈帧在虚拟机栈中入栈出栈的过程

在编译期间,栈帧需要多大的局部变量表、多深的操作数栈都已经完全确定,并且写入方法的code 属性中

一个栈帧需要分配多大内存,不会受到程序运行期变量数据影响

在活动线程中,栈顶的栈帧才是有效的,称为当前栈帧,相关联的方法称为当前方法

8.2.1局部变量表

是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量

在Java程序编译为class时,就在方法的code属性的max_locals数据项中确定了该方法所需分配的局部变量表的最大容量

局部变量表的容量以变量槽slot为最小单位

一个slot可以存放一个32位以内的数据,Java中32位以内的数据类型有:boolean、byte、char、short、int、float、reference、returnAddress


通过Reference类型可以:

从此引用直接或者间接的获取到对象在堆上存放的起始地址索引

此引用中直接或者间接的查找到对象所属数据类型在方法区的存储类型信息


对于64位(long,double)的数据类型,虚拟机采用高位对齐的方式为其分配两个slot空间

虚拟机通过索引定位的方式使用局部变量表

方法执行过程中,虚拟机通过局部变量表完成变量值到参数列表的传递过程

对于实例方法,局部变量表中第0位索引的slot默认传递方法所属对象实例的引用

为了节省栈帧空间,slot空间可以重用,但是会有额外的副作用,例如影响垃圾收集

8.2.2操作数栈(操作栈)

是一个后入先出栈

在编译时候写入code属性的max_stacks数据项中

操作数栈的每一个元素可以是任意的Java数据类型

32位数据类型占用的栈容量为1,64位数据类型占用的栈容量为2

操作数栈中元素的数据类型和字节码指令的序列严格匹配

概念模型上,两个栈帧完全相互独立,但大多虚拟机做了优化处理,使两个栈帧出现一部分重叠(方法调用可以共用一部分数据,无需进行额外的参数复制传递)

8.2.3动态连接

每个栈帧都有一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接

8.2.4方法返回地址

正常完成出口:PC计数器的值可以作为返回地址,栈帧中很可能保存这个计数值

异常完成出口:通过异常处理器表来确定返回地址,栈帧中一般不会保存这部分信息

方法退出等同于当前栈帧出栈,可能执行的操作有:

恢复上层方法的局部变量表和操作数栈,把返回值(如果有的话)压入调用者栈帧的操作数栈中,调整PC计数器的值以指向方法调用指令后面的一条指令

8.2.5附加信息


8.3方法调用

方法调用不等同于方法执行,唯一任务就是确定被调用方法的版本

8.3.1解析

调用目标在程序写好、编译器进行编译时就必须确定下来,这类方法的调用称为解析

编译期可知,运行期不变

静态方法

私有方法


相对应的5条方法调用字节码指令

invokestatic:调用静态方法

invokespecial:调用实例构造器init方法、私有方法、父类方法

invokevirtual:调用所有的虚方法

invokeinterface:调用接口方法,会在运行时再确定一个实现此接口的对象

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


只要能被invokestatic和invokespecial指令调用的方法,都可以再解析阶段中确定唯一的调用版本,符合这个条件的由静态方法、构造方法、私有方法、父类方法四大类,这些方法称为非虚方法(还包含final修饰的方法,无法被覆盖,没有其他版本);与之相反的称为虚方法(final修饰除外)

8.3.2分派

静态分派

静态类型(外观类型):变量本身的静态类型不会被改变,最终的静态类型是在编译期可知的

实际类型:变化结果在运行期才确定


使用哪个版本的重载,完全取决于传入参数的数量和数据类型;虚拟机(准确的说是编译器)在重载时是通过参数的静态类型而不是实际类型作为判定依据;并且静态类型是编译期可知的,因此,在编译阶段,javac编译器会根据参数的静态类型决定使用哪个版本的重载


所有依赖静态类型来定位方法执行版本的分派称为静态分派

静态分派的典型应用就是方法重载


动态分派

重写


invokevirtual的运行时解析过程:

找到操作数栈顶的第一个元素指向的对象的实际类型,记作C

如果类型C中找到与常量中的描述符和简单名称都相符的方法,则进行访问权限校验,如果通过则返回这个方法的直接引用,查找过程结束,如果不存在,则返回java.lang.IllegalAccessError异常

否则,按照继承关系从下往上依次对C的各个父类进行第二步的查搜索和验证过程

如果始终没有找到,则抛出java.lang.AbstractMethodError异常

运行期根据实际类型确定方法版本的分派称为动态分派


单分派和多分派

方法的接受者方法的参数统称为方法的宗量,根据分派基于多少种宗量,可以将分派划分为单分派和多分派

单分派是根据一个宗量对目标方法进行选择

多分派是根据多于一个宗量对目标方法进行分派

静态分派属于多分派

动态分派属于单分派


虚拟机动态分派的实现

方法表

8.3.3动态类型语言支持

动态类型语言

关键特征是类型检查的主体过程是在运行期而不是编译期

变量无类型而变量值有类型

静态类型语言在编译期提供严谨的类型检查

动态类型语言提供了更大的灵活性


JDK7与动态类型语言

invokedynamic指令以及java.lang.invoke包出现

java.lang.invoke包

提供了一种动态确定目标方法的机制,称为MethodHandle


MethodHandle和反射(Reflection)区别:

本质上将都是在模拟方法调用,但反射模拟Java代码层次的调用,MethodHandle模拟字节码层次的调用

反射中的java.lang.Method对象远比MethodHandle机制的java.lang.MethodHandle对象所彪悍的信息多,反射是重量级,MethodHandle是轻量级

MethodHandle优化

invokedynamic指令

每一处含有invokedynamic指令的地方都称为动态调用点

掌控方法分派规则


8.4基于栈的字节码解释执行引擎

8.4.1解释执行

javac编译器完成了程序代码经过词法分析、语法分析到抽象语法树,在遍历语法树生成线性的字节码指令流的过程

一部分在虚拟机之外进行,而解释器是在虚拟机内部,所以Java程序的编译是半独立的实现

8.4.2基于栈的指令集和基于寄存器的指令集

基于栈的指令集主要优点是可移植性、代码更加紧凑、编译实现更简单;缺点是执行速度相对慢点

8.4.3基于栈的解释器执行过程




参考文献:

[1] 深入理解Java虚拟机 第二版 --周志明

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

推荐阅读更多精彩内容