虚拟机栈概述

news2024/11/27 2:49:25

一、概述

1.1、虚拟机栈背景

        由于跨平台性的设计,Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的。

  • 优点是跨平台,指令集小,编译器容易实现,
  • 缺点是性能下降,实现同样的功能需要更多的指令。

1.2、虚拟机栈内容

1.2.1、虚拟机栈概念

        Java虚拟机栈(Java Virtual Machine Stack),早期也叫Java栈。每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),每个栈帧对应着一次的Java方法调用,是线程私有的。

1.2.2、生命周期

        Java虚拟机栈的生命周期和线程一致

1.2.3、作用

        主管Java程序的运行,保存方法的局部变量、部分结果,并参与方法的调用和返回。

1.2.4、栈的特点

        栈是一种快速有效的分配存储方式,访问速度仅次于程序计数器。JVM直接对Java栈的操作只有两个:

  • 每个方法执行,伴随着进栈(入栈、压栈)
  • 执行结束后的出栈工作

        对于栈来说不存在垃圾回收问题(栈存在溢出的情况)

1.3、栈开发中的异常

1.3.1、栈中可能出现的异常

        Java 虚拟机规范允许Java栈的大小是动态的或者是固定不变的。

  • 如果采用固定大小的Java虚拟机栈,那每一个线程的Java虚拟机栈容量可以在线程创建的时候独立选定。如果线程请求分配的栈容量超过Java虚拟机栈允许的最大容量,Java虚拟机将会抛出一个StackOverflowError 异常。如,程序不断的进行递归调用,而且没有退出条件,就会导致不断地进行压栈。
  • 如果Java虚拟机栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的虚拟机栈,那Java虚拟机将会抛出一个 OutOfMemoryError 异常。

二、栈的存储单位

2.1、栈中存储的内容

  • 每个线程都有自己的栈,栈中的数据都是以栈帧(Stack Frame)的格式存在。
  • 在这个线程上正在执行的每个方法都各自对应一个栈帧(Stack Frame)。
  • 栈帧是一个内存区块,是一个数据集,维系着方法执行过程中的各种数据信息。

2.2、栈运行原理

2.2.1、运行流程

  • JVM直接对Java栈的操作只有两个,就是对栈帧的压栈和出栈,遵循“先进后出”/“后进先出”原则。
  • 在一条活动线程中,一个时间点上,只会有一个活动的栈帧。即只有当前正在执行的方法的栈帧(栈顶栈帧)是有效的,这个栈帧被称为当前栈帧(Current Frame),与当前栈帧相对应的方法就是当前方法(Current Method),定义这个方法的类就是当前类(Current Class)。
  • 执行引擎运行的所有字节码指令只针对当前栈帧进行操作。
  • 如果在该方法中调用了其他方法,对应的新的栈帧会被创建出来,放在栈的顶端,成为新的当前帧。

2.2.2、注意

  • 不同线程中所包含的栈帧是不允许存在相互引用的,即不可能在一个栈帧之中引用另外一个线程的栈帧。
  • 如果当前方法调用了其他方法,方法返回之际,当前栈帧会传回此方法的执行结果给前一个栈帧,接着,虚拟机会丢弃当前栈帧,使得前一个栈帧重新成为当前栈帧。
  • Java方法有两种返回函数的方式,一种是正常的函数返回,使用return指令;另外一种是抛出异常。不管使用哪种方式,都会导致栈帧被弹出。

2.3、栈帧的内部结构

  • 局部变量表(Local Variables)
  • 操作数栈(operand Stack)(或表达式栈)
  • 动态链接(DynamicLinking)(或指向运行时常量池的方法引用)
  • 方法返回地址(Return Address)(或方法正常退出或者异常退出的定义)
  • 一些附加信息

2.3.1、局部变量表(本地变量表)

  • 定义为一个数字数组,主要用于存储方法参数和定义在方法体内的局部变量,这些数据类型包括各类基本数据类型、对象引用(reference),以及returnAddress类型。
  • 由于局部变量表是建立在线程的栈上,是线程的私有数据,因此不存在数据安全问题
  • 局部变量表所需的容量大小是在编译期确定下来的,并保存在方法的Code属性的maximum local variables数据项中。在方法运行期间是不会改变局部变量表的大小的。
  • 方法嵌套调用的次数由栈的大小决定。一般来说,栈越大,方法嵌套调用次数越多。对一个函数而言,它的参数和局部变量越多,使得局部变量表膨胀,它的栈帧就越大,以满足方法调用所需传递的信息增大的需求。进而函数调用就会占用更多的栈空间,导致其嵌套调用次数就会减少。
  • 局部变量表中的变量只在当前方法调用中有效。在方法执行时,虚拟机通过使用局部变量表完成参数值到参数变量列表的传递过程。当方法调用结束后,随着方法栈帧的销毁,局部变量表也会随之销毁。

1.slot变量槽

  • 局部变量表,最基本的存储单元是Slot(变量槽)
  • 参数值的存放总是在局部变量数组的index0开始,到数组长度-1的索引结束。
  • 局部变量表中存放编译期可知的各种基本数据类型(8种),引用类型(reference),returnAddress类型的变量。
  • 在局部变量表里,32位以内的类型只占用一个slot(包括returnAddress类型),64位的类型(long和double)占用两个slot。
    • byte、short、char 在存储前被转换为int,boolean也被转换为int,0表示false,非0表示true。
    • long、double占据两个Slot
  • JVM会为局部变量表中的每一个Slot都分配一个访问索引,通过这个索引即可成功访问到局部变量表中指定的局部变量值
  • 当一个实例方法被调用的时候,它的方法参数和方法体内部定义的局部变量将会按照顺序被复制到局部变量表中的每一个slot上
  • 如果需要访问局部变量表中一个64bit的局部变量值时,只需要使用前一个索引即可。(比如:访问long或doub1e类型变量)
  • 如果当前帧是由构造方法或者实例方法创建的,那么该对象引用this将会存放在index为0的slot处,其余的参数按照参数表顺序继续排列。

2.Slot的重复利用

        栈帧中的局部变量表中的槽位是可以重用的,如果一个局部变量过了其作用域,那么在其作用域之后申明的新的局部变就很有可能会复用过期局部变量的槽位,从而达到节省资源的目的。

3.静态变量和局部变量的对比

变量分类:

  • 按照数据类型分:基本数据类型,引用数据类型
  • 按照在类中声明的位置分:
    • 成员变量(static修饰静态变量,实例变量):使用前都经历过默认初始化赋值
      • 类变量:linking的prepare阶段,给类变量默认赋值;initial阶段,给类变量显式赋值即静态代码块赋值
      • 实例变量:随着对象的创建,在堆空间中分配实例变量空间,并进行默认赋值
    • 局部变量:在使用前,必须进行显式赋值,否则,编译不通过

 注意:局部变量表中的变量是垃圾回收的重要根节点。被局部变量表中直接或间接引用的对象都不会被回收。

2.3.2、操作数栈

        每个独立的栈帧中除了局部变量表之外还包含操作数栈(表达式栈)

  • 操作数栈,在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即入栈(push)和出栈(pop)
  • 操作数栈,主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。
  • 栈中的任何一个元素都可以是任意的Java数据类型
    • 32bit的类型占用一个栈单位深度
    • 64bit的类型占用两个栈单位深度
  • 操作数栈只能通过出入栈访问数据,不能使用索引

栈顶缓存技术

       将栈顶元素缓存在物理CPU的寄存器中,降低对内存的读写次数,提升执行引擎的执行效率。

2.3.3、动态链接

概念:

        每一个栈帧内部都包含一个指向运行时常量池该栈帧所属方法的引用。包含这个引用的目的就是为了支持当前方法的代码能够实现动态链接

方法的调用:

  • 静态链接:字节码文件装载至JVM时,被调用的方法在编译期可知
  • 动态链接:字节码文件装载至JVM时,被调用的方法在编译期不可知,在运行时可知

对应的绑定机制:绑定是一个字段、方法或类的符号引用被替换为直接引用的过程,只发生一次

  • 早期绑定:目标方法在编译期可知,且运行时保持不变
  • 晚期绑定:编译期无法确定,程序运行时根据实际类型绑定相关方法

虚方法和非虚方法:

  • 非虚方法:
  1. 编译期确定调用版本,在运行时不可变
  2. 静态方法、私有方法、final方法、实例构造器、父类方法都是非虚方法
  3. 其他方法称为虚方法

  • 虚方法表

 2.3.4、方法返回地址

        存放调用该方法的PC寄存器(该方法调用的下一条指令的值)的值

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

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

相关文章

网络分析和机器学习

文章目录 网络分析1.Introduction to networks and graph foundations and algorithmsNetwork types (social/bio/comp), Euler/Hamilton, Graphs (matrix/adj)Breadth-first search (shortest paths), Depth-first search (conn. compnts) 2. Emergent global / local network…

PS的基础操作

1、图片放大缩小alt鼠标滚轮 2、按住空格不放,拖拽鼠标可以改变图片的位置 3、英文状态下按字母t,再点击想要查看的文字,就可以在菜单栏上看到所有属性(取消选中按esc键) 4、点击它可以画选区来查看间距; w代表宽;h代表…

Jenkins版本升级

Jenkins版本过低的时候,一些插件无法升级,会引发一系列错误,这个时候我们就要升级版本了 一、下载更新包 第一种方式:Jenkins页面下载最新包 第二种官网上下载war包(Jenkins官网) 二、打开服务器搜索jenkins.war路径 1、如果Jenk…

CSDN 的 MD编辑器一些用法

一、点击关键语句跳转指定位置 在CSDN写文章的时候,写的文章过长往往会让读者很难找到自己想看的部分,这时候有个 跳转到指定位置功能 就非常的便利。CSDN在MD编辑器上(富文本编辑器只有一种)就提供了两种跳转到指定位置的方法: 一、目录转跳…

【SCADA】KingSCADA将数据插入SQLServer的方法

大家好,我是雷工! 本篇通过实例,介绍KingSCADA3.7访问SQL Server2022数据库。 一、概述 1、创建数据库及数据表格; 2、配置ODBC数据源。 3、通过KingSCADA与数据库建立连接,将数据写入数据库对应表格。 二、创建数据…

自动化测试与手工测试?你真的了解吗?如何共存...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 Python自动化测试&…

代码随想录算法训练营第二十七天|39. 组合总和 40.组合总和II131.分割回文串

文章目录 39. 组合总和思路代码总结 40.组合总和II思路代码总结 131.分割回文串思路代码总结 39. 组合总和 思路 我举过例子,如果是一个集合来求组合的话,就需要startIndex,例如:77.组合 ,216.组合总和III 。 如果是…

【AIGC使用教程】Microsoft Edge/Bing Chat 注册使用完全指南

欢迎关注【AIGC使用教程】 专栏 【AIGC使用教程】SciSpace 论文阅读神器 【AIGC使用教程】Microsoft Edge/Bing Chat 注册使用完全指南 【AIGC使用教程】GitHub Copilot 免费注册及在 VS Code 中的安装使用 【AIGC使用教程】GitHub Copilot 免费注册及在 PyCharm 中的安装使用 …

算法时间复杂度

参考视频&#xff1a;https://www.bilibili.com/video/BV14j411f7DJ 目录 1.常数阶O(1) 2.对数阶O(IogN) 3.线性阶O(n) 4.线性对数阶O(nlogN) 5.平方阶O(n^2) 6.立方阶O(n^3) 7.K次方阶O(n^k) 8.指数阶(2^n) 9.阶乘O(n!) 两层for循环 for (int i 1; i <…

有模型强化学习和免模型强化学习有什么区别?

有模型强化学习&#xff08;Model-Based Reinforcement Learning&#xff09;和无模型强化学习&#xff08;Model-Free Reinforcement Learning&#xff09;是两种不同的强化学习方法。 有模型强化学习是指&#xff0c;智能体在学习过程中能够对环境进行建模&#xff0c;即学习…

软件测试分类: 你需要知道的不同类型测试

文章目录 一. 按测试对象进行划分1. 界面测试2. 可靠性测试3. 容错性4. 文档测试5. 兼容性测试6. 易用性测试7. 安装卸载的测试8. 安全测试9. 性能测试10. 内存泄漏测试 二. 按是否查看代码划分1. 黑盒测试(Black-box Testing)2. 白盒测试(White-box Testing)冒泡排序测试用例进…

【1 Vue基础 - 模板语法-绑定】

1 VSCode代码片段 链接: link 2 Mustache双大括号语法 插入内容 <body><div id"app"><!-- 1.基本使用 --><h2>{{ message }}</h2><h2>当前计数: {{ counter }} </h2><!-- 2.表达式 --><h2>计数双倍: {{ c…

研发项目工时统计工具哪个好?9大工时管理系统盘点

工时管理是项目型企业的重要需求&#xff0c;特别是在人力成本占比较高的行业&#xff0c;如软件开发、设计咨询、会计律师等。工时管理可以帮助企业核算项目人工成本&#xff0c;控制成本投入&#xff0c;提高项目利润&#xff0c;客观考核员工绩效&#xff0c;优化资源分配等…

C++类和对象入门(中)

C类和对象入门 中 1. 类的6个默认成员函数2. 构造函数2.1 概念2.2 特性 3.初始化列表4.析构函数4.2 特性 5. 拷贝构造函数5.1 特性 6.运算符重载6.1 赋值运算符重载6.2前置和后置重载 7. 自实现日期类 1. 类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空…

golang 服务中 context 超时处理的思考

文章目录 前言起因&#xff1a;日志告警引发的思考什么是contextcontext的作用context超时之后继续执行 or 中断 最后 前言 公司运行的服务代码中&#xff0c;随处可见各种各样的日志信息&#xff0c;其中大多数是用来记录各种异常的日志&#xff0c;一方面&#xff0c;当出现…

煤矿电子封条实施方案 yolov7

煤矿电子封条实施方案采用YOLOv7网络模型算法技术&#xff0c;煤矿电子封条实施算法模型过将全国各省矿山实时监测数据&#xff0c;实现对全国各矿山及时有效的处理及分析。YOLOv7 的发展方向与当前主流的实时目标检测器不同&#xff0c;研究团队希望它能够同时支持移动 GPU 和…

Arthas实现热更新代码

目录 1.Arthas简介 2.准备Demo 3.启动Arthas 4.Arthas命令 5.使用retransform命令热更新代码 1.Arthas简介 Arthas 是一款线上监控诊断产品&#xff0c;通过全局视角实时查看应用 load、内存、gc、线程的状态信息&#xff0c;并能在不修改应用代码的情况下&#xff0c;对…

Python中的模块2

为了加快导入模块的速度&#xff0c;Python会缓存之前使用过的模块。 1 保存缓存文件的路径 Python会将之前编译过的模块保存在与该模块同一目录中的“__pycache__”文件夹中。 2 缓存文件名 缓存文件会以“模块名.版本号.pyc”格式命名。图1为使用yang_module.py模块后得到…

2023年NOC大赛创客智慧编程赛项图形化复赛模拟题一,包含答案解析

2023年NOC大赛创客智慧编程赛项图形化复赛模拟题一,包含答案解析 本次题目来源:NOC 大赛创客智慧编程赛项图形化复赛模拟题(一) 第一题: 制作一个生日贺卡小程序. 1.点击绿旗后蛋糕出现在 (0,-80) 的位置,大小为 100,造型为 cake-b2.当碰到鼠标指针时,将造型切换为 ca…

【EasyAR实战项目】图像识别+模型交互(全网首发,保姆级教程)

话不多说&#xff0c;先看实现效果 开发准备 以下为作者开发的环境&#xff0c;当然也可以使用更高的版本&#xff0c;尤其是EasyAR的版本可以选择更高的&#xff0c;因为这玩意儿版本迭代的太快了&#xff0c;而且更高版本所支持的手机型号更新&#xff0c;兼容性更强。 1 U…