运行时栈帧结构与方法调用

news2024/10/6 8:27:38

 1 运行时栈帧结构

Java虚拟机以方法作为最基本执行单元,“栈帧”则是用于支持虚拟机进行方法调用和方法执行背后的数据结构。栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息。

1.1 局部变量表

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

Java虚拟机通过索引定位的方式使用局部变量表。如果访问的是64位数据类型的变量,则说明会同时使用第N和第N+1两个变量槽。虚拟机不允许采用任何方式单独访问其中的某一个。

reference类型表示对一个对象实例的引用,《Java虚拟机规范》既没有说明它的长度,也没明确指出这种引用的结构。但是一般来说,引用类型至少有两项作用:

1)从根据引用直接或间接地查找到对象在Java堆中的数据存放的起始地址或索引。

2)根据引用直接或间接地查找到对象所属数据类型在方法区的存储的类型信息。

1.1.1 实参到形参的传递

当一个方法被调用时,Java虚拟机会使用局部变量表来完成参数值到参数变量列表的传递。如果执行的是实例方法,那局部变量表中第0位索引的变量槽默认是用于传递方法所属对象实例的引用。其余参赛按照参赛表顺序排列。

1.1.2 变量槽重用

局部变量表中的变量槽是可以重用的,方法体中定义的变量,其作用域并不一定会覆盖整个方法体,如果当前字节码PC计数器的值已经超出了某个变量的作用域,那这个变量对应的变量槽就可以交给其他变量来重用。

1.2 操作数栈

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

在大多虚拟机的实现里,会进行一些优化处理,令两个栈帧出现一部分重叠。

图 操作数栈重叠实例代码

两个栈帧一部分重叠主要体现在方法中有参数传递的情况。

图 操作数栈重叠代码帧栈重叠部份图示

这样做不仅节约了一些空间,更重要的是在进行方法调用时就可以直接共用一部分数据,无须进行额外的参数复制传递了。

2方法调用

方法调用并不等同于方法中的代码被执行,方法调用阶段唯一的任务就是确定被调用方法的版本(即调用哪一个方法)。程序运行时,进行方法调用是最普遍、最繁琐的操作之一。

2.1 解析

在类加载的解析阶段,会将方法中的一部分符号引用转化为直接引用,这种解析能够成立的前提是:方法在程序真正运行之前就有一个可确定的调用版本,并且这个方法的调用版本在运行期不可改变。

符合“编译器可知,运行期不可变”这个要求的方法,主要有静态方法和私有方法这两大类。

invokestatic

调用静态方法

invokespecial

调用实例构造器<init>()方法、私有方法和父类中的方法

invokevirtual

调用所有的虚方法

invokeinterface

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

invokedynamic

先在运行时动态解析出调用点限定符所引用的方法,然后再执行该方法。前面4条分派逻辑都固化在Java虚拟机内部,而这条指令分派逻辑是由用户设定的引导方法来决定的。

表 Java虚拟机支持的方法调用字节码指令

2.1.1 非虚方法和虚方法

只要能被invokestatic和invokespecial指令调用的方法及被final修饰的方法(尽管它使用invokevirtual指令调用),都可以在解析阶段中确定唯一的调用版本。这些方法被称为“非虚方法”。与之相反的其他方法被称为“虚方法”。

图 方法静态解析演示

2.2 分派

2.1.1 静态分派

静态分派是编译器方法重载的过程。

静态类型(也叫外观类型)在编译器是可知的。而实际类型(也叫运行时类型)要等到运行期才可知。

如:Human man = new Man(); 静态类型为Human,实际类型为Man。

方法重载哪个版本,完全取决于传入参数的数量和数据类型,但虚拟机在重载时是通过参数的静态类型作为判定依据的。

2.1.2 动态分派

动态分派和重写有着很密切的关联。

public class DynamicAllocation {

    private static class Human {
        void sayHello() {
            System.out.println("Hello Human");
        }
    }

    private static class Man extends Human {
        @Override
        void sayHello() {
            System.out.println("Hello Man");
        }
    }

    public static void main(String[] args) {
        Human human = new Man();
        human.sayHello();
    }
}
/*
运行结果:
Hello Man
 */

图 上述代码的部份字节码

标红处为main方法中执行sayHello方法的地方。根据《Java虚拟机规范》,invokevirtual指令的运行时解析过程大致分为以下步骤:

  1. 找到操作数栈顶顶第一个元素所指的对象的实际类型,记作C。
  2. 如果在类型C中找到与常量中的描述符和简单名称都相符的方法,则进行校验,如果通过则返回这个方法的直接引用,查找过程结束;不通过则返回java.lang.IllegalAccessError异常。
  3. 否则,按照继承关系从下往上依次对C的各个父类进行第二步的搜索和验证过程。
  4. 如果始终没有找到合适的方法,则抛出java.lang.AbstractMethodError异常。

指令的第一步就是在运行期确定接收者的实际类型,这个过程是Java语言中方法重写的本质。

字段不可能是虚的。

2.1.3 单分派与多分派

方法的接收者与方法的参数统称为方法的宗量。根据分派基于多少种宗量,将分派划分为单分派和多分派两种。

至今的Java语言是一门静态(和接收者及方法的参数都有关,重载)多分派、动态单分派(只和接收者有关)的语言。

2.1.4 虚拟机动态分派的实现

使用虚方法索引来代替元数据查找以提高性能。虚方法表存放着各个方法的实际入口地址。如果某个方法在子类中没有被重写,那子类的虚方法表中的地址入口和父类相同方法的地址入口是一样的。如果重写了这个方法,子类虚方法表中的地址也会被替换为指向子类实现版本的入口地址。

为了程序实现方便,具有相同签名的方法,在父类、子类的虚方法表中都应当具有一样的索引号,这样当类型变换时,仅需变更查找的虚方法表。

虚方法表一般在类加载的连接阶段进行初始化,准备了类的变量初始值后,虚拟机会把该类的虚方法表也一同初始化完毕。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/539874.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

强化学习:贝尔曼方程(Bellman Equation)

∗ ∗ 重点&#xff1a;状态值、贝尔曼方程 ∗ ∗ **重点&#xff1a;状态值、贝尔曼方程** ∗∗重点&#xff1a;状态值、贝尔曼方程∗∗ return评估策略 在前面概念介绍中&#xff0c;我们知道了可以用 return 来评估一个策略的好坏。如图&#xff0c;有三个不同的策略&…

线性插值提高DDS相位分辨率

DDS&#xff08;Direct Digital Synthesizer&#xff09;即直接数字频率合成技术&#xff0c;主要由正弦查找表与控制器组成&#xff0c;通过控制器给出的相位&#xff0c;在正弦查找表中查找对应的正余弦值并予以输出。通过多个 DDS 信号的组合&#xff0c;可以进一步构建出 A…

【源码解析】Disruptor框架的源码解析

Disruptor初始化 初始化Disruptor实例 //单线程模式&#xff0c;获取额外的性能 Disruptor<MessageModel> disruptor new Disruptor<>(factory, bufferSize, executor,ProducerType.SINGLE, new BlockingWaitStrategy());创建RingBuffer实例 Deprecatedpublic D…

Midjourney|文心一格prompt教程[Text Prompt(上篇)]:品牌log、App、徽章、插画、头像场景生成,各种风格选择:科技风、运动风

Midjourney|文心一格prompt教程[Text Prompt&#xff08;上篇&#xff09;]&#xff1a;品牌log、App、徽章、插画、头像场景生成&#xff0c;各种风格选择&#xff1a;科技风、运动风 1.撰写 Text Prompt 注意事项 Midjourney 跟 ChatGPT 在 prompt 的使用上有很多不一样的地…

怎么做好媒体邀约

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好 要做好媒体邀约&#xff0c;以下是一些关键步骤和建议&#xff1a; 1. 制定媒体邀约方案&#xff1a;首先&#xff0c;确定您希望邀约的目标媒体。了解他们的受众、内容定位和报道风格&#xff0c;确保与您的品牌和目标受众…

ChatGPT 的工作原理:深入探究

本文首发于微信公众号&#xff1a;大迁世界, 我的微信&#xff1a;qq449245884&#xff0c;我会第一时间和你分享前端行业趋势&#xff0c;学习途径等等。 更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi &#xff0c;包含一线大厂面试完整考点、资料以及我的…

opencv实践项目-图片拼接之缝合线算法

目录 1. stitcher_detail执行过程2. 源码3. stitching_detail 程序接口介绍4. 执行5. 结果图 1. stitcher_detail执行过程 stitcher_detail是opencv官网提供的一个用于多福图像拼接的Demo&#xff0c;其主要过程如下&#xff1a; 1.输入待拼接图像集合&#xff1b;2.分别对每幅…

Jetson Nano调试记录:机电设备控制

边缘应用中,机电控制是一项非常重要的能力。 当我们的智能设备在远端环境中,根据所识别的状况变化去执行应对措施,更大程度度地降低对人为操作的依赖,这些都是能产生更大经济效益的应用,包括无人驾驶车、自动机械手臂等等。 实际工业应用场景中的控制元件是非常多样化的,…

惠普暗影精灵5 super 873-068rcn怎样用u盘重装系统win10

当我们的戴尔电脑出现问题的时候&#xff0c;无法进入系统要怎么重装系统win10修复呢?比较常用的就是借助u盘重装系统win10&#xff0c;需要用到装机工具。下面就给大家详细介绍下戴尔电脑怎样用u盘重装系统win10教程。 工具/原料&#xff1a; 系统版本&#xff1a;windows1…

LSTM-理解 Part-3(LSTM Networks)

之前博客中有涉及前两部分的介绍&#xff1a; 第一部分LSTM-理解 Part-1&#xff08;RNN&#xff1a;循环神经网络&#xff09; 第二部分LSTM-理解 Part-2&#xff08;RNN的局限性&#xff09; 这是其中的第三部分&#xff0c;讲解 LSTM Networks。 LSTM Networks 长短期记忆网…

【Python MySQL】零基础也能轻松掌握的学习路线与参考资料

Python是一种广泛使用的编程语言&#xff0c;MySQL是一个流行的关系数据库管理系统。学习Python和MySQL可以帮助开发人员更有效地处理数据&#xff0c;并构建可扩展和强大的Web应用程序。本文将介绍Python MySQL学习路线&#xff0c;参考资料和优秀实践。 Python MySQL学习路线…

美的智家、海尔智家,吹响新一轮AI竞赛号角

ChatGPT大行其道&#xff0c;各行各业迫不及待披上了AI大模型的“盔甲”&#xff0c;有的企业自研AI大模型&#xff0c;有的企业牵手头部科技企业&#xff0c;寻求智能产品价值的最大化&#xff0c;智能家电行业也不例外。 在国内&#xff0c;百度AI大模型文心一言一经推出就吸…

卷绕模型介绍

卷绕模型是收放卷应用的基础知识,这篇博客帮大家整理分析,有关收放卷的其它相关基础知识请参看专栏相关文章。和这篇文章相关联的知识点大家可以参看下面的博客 体积法计算卷径详细介绍 卷径计算详解(通过卷绕的膜长和膜厚进行计算)_RXXW_Dor的博客-CSDN博客有关卷绕+张力控…

LoRA:大模型的低秩自适应微调模型

对于大型模型来说&#xff0c;重新训练所有模型参数的全微调变得不可行。比如GPT-3 175B&#xff0c;模型包含175B个参数吗&#xff0c;无论是微调训练和模型部署&#xff0c;都是不可能的事。所以Microsoft 提出了低秩自适应(Low-Rank Adaptation, LoRA)&#xff0c;它冻结了预…

企业级体验:未来体验管理的价值与趋势

我从事企业级体验相关领域的工作已十六载有余&#xff0c;曾经就职的企业既有阿里巴巴、腾讯这样的互联网“大厂”&#xff0c;也有顺丰、龙湖这样的线下“传统”企业。在这些企业中&#xff0c;我所工作的场景横跨了软件、电商、互联网、物流、零售、地产、金融等诸多业务领域…

11.计算机基础-计算机网络面试题—基础知识

本文目录如下&#xff1a; 计算机基础-计算机网络 面试题一、基础知识简述 TCP 和 UDP 的区别&#xff1f;http 与 https的区别?Session 和 Cookie 有什么区别&#xff1f;详细描述一下 HTTP 访问一个网站的过程&#xff1f;https 是如何实现加密的&#xff1f;URL是什么&…

Linux下网络编程(3)——socket编程实战,如何构建一个服务器和客户端连接

经过前几篇的介绍&#xff0c;本文我们将进行编程实战&#xff0c;实现一个简单地服务器和客户端应用程序。 编写服务器程序 编写服务器应用程序的流程如下&#xff1a; ①、调用 socket()函数打开套接字&#xff0c;得到套接字描述符&#xff1b; ②、调用 bind()函数将套接字…

Deep Supervised Dual Cycle Adversarial Network for Cross-Modal Retrieval 论文阅读笔记

​# 1. 论文信息 论文名称Deep Supervised Dual Cycle Adversarial Network for Cross-Modal Retrieval作者Lei Liao 中山大学会议/出版社IEEE Transactions on Circuits and Systems for Video Technologypdf&#x1f4c4;在线pdf代码&#x1f4bb;无代码 本文是基于公共空间…

mov转换为mp4格式怎么转,多方法教程

mov转换为mp4格式怎么转&#xff1f;如果你连mov都不了解&#xff0c;那就更别说将其进行转换了。其实使用过苹果手机的人应该接触的很多&#xff0c;但是我们时常不关注这个视频格式。MOV是一种音频和视频文件格式&#xff0c;它在苹果手机上使用。它不兼容安卓或Windows电脑&…

cookie、session、JWT(Json Web Token) 的区别?

cookie、session、JWT(Json Web Token) 的区别&#xff1f; 答&#xff1a; 要从http的无状态说起&#xff0c;http是无状态的&#xff0c;也就是如果你第一次访问服务器&#xff0c;之后再次访问的时候&#xff0c;服务器是不会意识到你再次来进行访问的。不想让已经登录的用…