深入理解Java虚拟机:Jvm总结-虚拟机字节码执行引擎

第八章 虚拟机字节码执行引擎

8.1 意义

不受物理条件制约地定制指令集与执行引擎的结构体系,能够执行那些不被硬件直接支持的指令集格式。输入的是字节码二进制流,处理过程是字节码解析执行的等效过程,输出的是执行结果

8.2 运行时栈帧结构

  • 栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息
    在这里插入图片描述

以Java程序的角度来看,同一时刻、同一条线程里面,在调用堆栈的所有方法都同时处于执行状态。而对于执行引擎来讲在活动线程中,只有位于栈顶的方法才是在运行的,只有位于栈顶的栈帧才是生效的,其被称为“当前栈帧”(Current Stack Frame),与这个栈帧所关联的方法被称为“当前方法”(Current Method)

  • 编译Java程序源码的时候,栈帧中需要多大的局部变量表,需要多深的操作数栈就已经被分析计算出来,也就是一个栈帧需要分配多少内存,并不会受到程序运行期变量数据的影响,而仅仅取决于程序源码和具体的虚拟机实现的栈内存布局形式

8.2.1 局部变量表

  • 存放方法参数和方法内部定义的局部变量,编译时就确定了该方法局部变量表的最大容量。
  • 变量槽(Slot)为最小单位,一个变量槽可以存放一个32位以内的数据类型,对于64位的数据类型,Java虚拟机会以高位对齐的方式为其分配两个连续的变量槽空间。Java语言中明确的64位的数据类型只有long和double两种
  • Java虚拟机通过索引定位的方式使用局部变量表,索引值的范围是从0开始至局部变量表最大的变量槽数量。
  • 当一个方法被调用时,Java虚拟机会使用局部变量表来完成参数值到参数变量列表的传递过程,即实参到形参的传递。如果执行的是实例方法, 表中第0位索引,默认是记录方法所属对象实例的引用。
  • 变量槽可以重用,但是可能会影响垃圾收集
  • 局部变量不初始化不能使用

8.2.2 操作数栈

  • 当一个方法刚刚开始执行的时候,这个方法的操作数栈是空的,在方法的执行过程中,会有各种字节码指令往操作数栈中写入和提取内容,也就是出栈和入栈操作。顾名思义,就是用来操作的。

  • 操作数栈中元素的数据类型必须与字节码指令的序列严格匹配,也就是说用于整型值的操作,不能使用其他的值。

  • 栈帧可以一部分重叠,可以共用一部分数据

8.2.3 动态连接

每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,符号引用一部分会在类加载阶段或者第一次使用的时候就被转化为直接引用,这种转化被称为静态解析。另外一部分将在每一次运行期间都转化为直接引用,这部分就称为动态连接

8.2.4 方法返回地址

当一个方法开始执行后,只有两种方式退出这个方法:

  • 第一种方式是执行引擎遇到任意一个方法返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者
  • 另外一种退出方式是在方法执行的过程中遇到了异常

一般来说,方法正常退出时,主调方法的PC计数器的值就可以作为返回地址,而方法异常退出时,返回地址是要通过异常处理器表来确定的。

8.3 方法调用

方法调用阶段唯一的任务就是确定调用哪个方法,不涉及方法内部细节

8.3.1 解析

解析是指当一个方法被调用时,JVM 如何确定实际要执行的方法。这里的解析调用具体为:方法的调用版本在编译期间就完全确定,在类加载的解析阶段就会把涉及的符号引用全部转变为明确的直接引用,在运行期是不可改变的方法。

主要有静态方法和私有方法两类,适合在类加载阶段进行解析

有五种调用方法的字节码指令:

  • invokestatic 用于调用静态方法
  • invokespecial 用于调用实例构造器()方法、私有方法和父类中的方法
  • invokevirtual用于调用所有的虚方法
  • invokeinterface用于调用接口方法,会在运行时再确定一个实现该接口的对象
  • invokedynamic先在运行时动态解析出调用点限定符所引用的方法,然后再执行该方法,由用户制定逻辑,前4种固定在虚拟机内部

只要能被invokestatic和invokespecial指令调用的方法,都可以在解析阶段中确定唯一的调用版本,Java语言里符合这个条件的方法共有静态方法、私有方法、实例构造器、父类方法4种,再加上被final修饰的方法(尽管它使用invokevirtual指令调用),这5种方法调用会在类加载的时候就可以把符号引用解析为该方法的直接引用。这些方法统称为“非虚方法”(Non-Virtual Method),与之相反,其他方法就被称为“虚方法”(Virtual Method)。

8.3.2 分派

分派调用是一种方法调用形式,可以是静态的也可是动态的。分派具有动态性,可以揭示多态的特性,比如重写和重载,根据实际代码更好理解

  1. 静态分派
    • 所有依赖静态类型来决定方法执行版本的分派动作,都称为静态分派。静态分派的最典型应用表
      现就是方法重载。静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机来执行
      的。
    • 虚拟机(或者准确地说是编译器)在重载时是通过参数的静态类型而不是实际类型作为
      判定依据的。由于静态类型在编译期可知,所以在编译阶段,Javac编译器就根据参数的静态类型决定
      了会使用哪个重载版本
    • 需要注意Javac编译器虽然能确定出方法的重载版本,但在很多情况下这个重载版本并不是“唯
      一”的,往往只能确定一个“相对更合适的”版本
  2. 动态分派
    • 在运行期根据实际类型确定方法执行版本的分派过程称为动态分派。也就是方法重写的本质
    • 根源在于虚方法调用指令invokevirtual的执行逻辑:
      1. 找到操作数栈顶的第一个元素所指向的对象的实际类型,记作C
      2. 如果在类型C中找到与常量中的描述符和简单名称都相符的方法,则进行访问权限校验,如果通过则返回这个方法的直接引用,查找过程结束;不通过则返回java.lang.IllegalAccessError异常。
      3. 否则,按照继承关系从下往上依次对C的各个父类进行第二步的搜索和验证过程
      4. 如果始终没有找到合适的方法,则抛出java.lang.AbstractMethodError异常
    • 在Java里面只有虚方法存在,字段永远不可能是虚的,换句话说,字段永远不参与多态。当子类声明了与父类同名的字段时,虽然在子类的内存中两个字段都会存在,但是子类的字段会遮蔽父类的同名字段
  3. 单分派与多分派
    • 方法的接收者与方法的参数统称为方法的宗量,单分派是根据一个宗量对目标方法进行选择,多分派则是根据多于一个宗量对目标方法进行选择。
  4. 虚拟机动态分派的实现
    • 动态分派的方法版本选择过程需要运行时在接收者类型的方法元数据中搜索合适的目标方法
    • 一种优化方法是为类型在方法区中建立一个虚方法表,使用虚方法表索引来代替元数据查找以提高性能
    • 虚方法表中存放着各个方法的实际入口地址。如果某个方法在子类中没有被重写,那子类的虚方法表中的地址入口和父类相同方法的地址入口是一致的,都指向父类的实现入口。如果子类中重写了这个方法,子类虚方法表中的地址也会被替换为指向子类实现版本的入口地址。
    • 虚方法表一般在类加载的连接阶段进行初始化,准备了类的变量初始值后,虚拟机会把该类的虚方法表也一同初始化完毕。
    • 除此之外,还会使用类型继承关系分析(Class Hierarchy Analysis,CHA)、守护内联(Guarded Inlining)、内联缓存(InlineCache)等多种非稳定的激进优化来争取更大的性能空间

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

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

相关文章

git如何灵活切换本地账号对应远程github的两个账号

git如何灵活切换本地账号对应远程github的两个账号 问题: 有时候我们会同时维护两个github的账号里面的仓库内容,这时候本地git需要频繁的切换ssh,以方便灵活的与两个账号的仓库可以通信。这篇日记将阐述我是怎么解决这个问题的。1. 第一个账…

通过HTforWeb在ARMxy边缘计算网关上实现工业互联网

随着工业互联网技术的不断进步和发展,企业越来越重视通过数字化手段提高生产效率、降低成本并增强竞争力。ARMxy BL340系列作为一款高性能的工业级ARM嵌入式计算机,为实现这些目标提供了坚实的硬件基础。而HTforWeb作为一款专业的前端开发工具&#xff0…

神经网络学习笔记——如何设计、实现并训练一个标准的前馈神经网络

1.从零设计并训练一个神经网络https://www.bilibili.com/video/BV134421U77t/?spm_id_from333.337.search-card.all.click&vd_source0b1f472915ac9cb9cdccb8658d6c2e69 一、如何设计、实现并训练一个标准的前馈神经网络,用于手写数字图像的分类,重…

九、外观模式

外观模式(Facade Pattern)是一种结构型设计模式,有叫门面模式,它为一个复杂子系统提供一个简单的接口,隐藏系统的复杂性。通过使用外观模式,客户端可以更方便地和复杂的系统进行交互,而无需直接…

【Android】【Bug】Activity全屏(保留底部按钮)被打断变成非全屏了

问题 在Activity里面设置全屏显示(保留底部按钮的全屏),刚开始的时候显示的也是全屏,但是在此页面进行一些操作之后,全屏变成非全屏了。 全屏设置方法 在 Activity 中的 onCreate 方法里,添加以下代码: Override p…

微信文件处理与命名机制分析(基于微信 8.0.50 版本)

微信文件处理与命名机制分析(基于微信 8.0.50 版本) 摘要 微信作为一款广泛使用的即时通讯工具,涉及图片、视频、文档等多种文件类型的传输与管理。本文基于微信 8.0.50 版本,探讨其对于图片、GIF、视频等文件的命名处理策略&am…

数据驱动的生态系统架构:打造智能化管理与业务增长的未来战略

在当今的数字化经济中,数据已成为企业最具战略价值的资产。通过数据的分析与应用,企业不仅能够提高业务效率,还能通过构建数据驱动的生态系统架构,实现跨行业协作与技术创新,最终提升全球竞争力。2024年生态系统架构可…

SpringBoot Jar 包加密防止反编译实战

今天给大家分享一个 SpringBoot 程序 Jar 包加密的方式,通过代码加密可以实现无法反编译。 应用场景就是当需要把公司的产品部署到友方公司或者其他公司时,可以防止客户直接反编译出来源码,大大提升代码的安全性。 版本 springboot 2.6.8j…

RuoYi 开源框架,集成了后端管理,后端java版 App 移动解决方案

文章目录 前言一、后端:二、后台管理三、App 移动总结 前言 后端: 后台管理: 使用的前端技术Vue、Element后端SpringBoot & Security完全分离的权限管理系统。 App 移动解决方案:采用uniapp框架 提示:以下是本篇文…

Java后端编程语言进阶篇

第一章 函数式接口 函数式接口是Java 8中引入的一个新特性,只包含一个抽象方法的接口。 函数式接口可以使用Lambda表达式来实现,从而实现函数式编程的特性。 使用 FunctionalInterface标识接口是函数式接口,编译器才会检查接口是否符合函数…

Qt 实现自定义截图工具

目录 Qt 实现自定义截图工具实现效果图PrintScreen 类介绍PrintScreen 类的主要特性 逐步实现第一步:类定义第二步:初始化截图窗口第三步:处理鼠标事件第四步:计算截图区域第五步:捕获和保存图像 完整代码PrintScreen.…

《程序猿之设计模式实战 · 池化思想》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…

“xi” 和 “dbscan” 在OPTICS聚类中是什么意思

在 OPTICS(Ordering Points To Identify the Clustering Structure) 聚类算法中,xi 和 dbscan 是两种不同的聚类提取方法,它们用于从OPTICS算法生成的排序数据中提取最终的聚类结构。具体解释如下: dbscan 方法: 该方法…

LSS如何做深度和语义预测

get_cam_feats() 先来看看代码: def get_cam_feats(self, x):"""Return B x N x D x H/downsample x W/downsample x C"""B, N

PHP函数如何传递数组参数

php 函数可以使用数组参数传递大量数据。语法:参数类型前加上方括号 ([])。例如:myfunction(array $arr)。实战案例:计算数组元素平均值。注意:数组参数默认为引用传递,类型提示可提高代码可读性,数组解构可…

解锁编程潜力,从掌握GitHub开始

目录: 一、搜索开源项目 1、什么是Git 2、Github常用词含义 3、一个完整的项目界面 4、使用Github搜索项目 1)in关键词 2)star或fork数量去查找 3)awesome加强搜索 二、访问速度慢的解决 1、使用网易UU加速器 2、使用…

OpenSSL工具验证RSA证书

openssl x509 是一个用于处理 X.509 证书的命令行工具。常用的 openssl x509 命令&#xff1a; -in <file>&#xff1a;指定输入文件。-out <file>&#xff1a;指定输出文件。-noout&#xff1a;不输出证书信息。-text&#xff1a;以文本格式输出证书信息。-pubke…

基于SSM的大学新生报到系统+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

关于RabbitMQ消息丢失的解决方案

RabbitMQ如何保证消息的可靠性传输 一、消息丢失的原因 1. 生产者端 网络问题&#xff1a; 原因&#xff1a;生产者与RabbitMQ服务器之间的网络连接不稳定或中断&#xff0c;导致消息在传输过程中丢失。解决方案&#xff1a;确保网络连接稳定&#xff0c;监控网络状态&#x…

springboot后端开发-常见注解及其用途

文章目录 1. 组件注解2. 依赖注入注解3. 配置类注解4. 测试注解5. 控制器注解6. 安全和认证注解7. 切面相关注解8. API文档相关注解(需引入swagger)9. 其他注解 在Spring Boot框架中&#xff0c;有许多常用的注解用来简化开发过程中的依赖注入、组件扫描、配置、安全控制等方面…