JVM之运行时栈帧的结构(基于《深入理解Java虚拟机》之第八章虚拟机字节码执行引擎)(上)_asasdadsadas-程序员宅基地

技术标签: jvm  java  # 重拳出击之《JVM》篇  字节码执行引擎  class  

asdas 执行引擎是Java虚拟机核心的组成部分之一。
asdsadasdasdasdasdasdsadasdasdsadassadasdas————《Java虚拟机规范》


物理机和虚拟机的执行引擎有什么区别呢?
sad
sdasd物理机的执行引擎: 直接建立在处理器、缓存、指令集和操作系统层面上的;
sdasd虚拟机的执行引擎: 由软件自行实现的,因此可以不受物理条件制约地定制指令集与执行引擎的结构体系,能够执行那些不被硬件直接支持的指令集格式。
sad
执行引擎的概念模型的作用是什么?
sad
sdasd在《Java虚拟机规范》中指定了执行引擎的概念模型,作为各大发行商的Java虚拟机执行引擎的统一外观
sdasd在不同的JVM中,执行引擎在执行字节码的时候通常会有两种选择:①、解释执行(解释器) ②、编译执行(JIT) 。
sdd【注】: 有的虚拟机只又其中的一个,比如Sun公司的Classic VM只有解释器,BEA的JRockit只存在编译执行。
sad
虚拟机的执行单位是什么?
sad
sdasd在第六章Class文件结构中我们就讲了,JVM是以方法作为最基本的执行单位。每一个方法从调用开始至执行结束的过程,都对应着一个栈帧在虚拟机栈里面从入栈到出栈的过程。
sad
栈帧包括什么?
sad
sdasd每一个栈帧包括:局部变量表、操作数栈、动态连接、方法返回地址和一些额外的附加信息。
sdasd在编译时期,栈帧需要多大的局部变量表,多深的操作数栈就已经被计算出来,并写入到了方法表的Code属性中。
sdasd总之,一个栈帧需要分配多少内存,并不会受到程序运行期变量数据的影响,而仅仅取决于程序源码和具体的虚拟机实现的栈内存布局形式(可能有重叠部分)
sad
当前栈帧指什么?
sad
sdasd以Java程序的角度来看:同一时刻、同一条线程里面,在调用堆栈的所有方法都同时处于执行状态。
sdasd对于执行引擎来讲:在活动线程中,只有位于栈顶的方法才是运行的,可以生效的,被称为"当前栈帧"。
sad
sdasadasdsadasadasdsasdasdsasadsd栈帧的概念结构图如下:
在这里插入图片描述


局部变量表是什么?
sad
sdasd局部变量表是一组变量值的存储空间,用于存放方法参数和方法内部定义的局部变量
sdasd在编译为Class文件时,就在方法的Code属性的max_locals数据项中确定了该方法所需分配的局部变量表的最大容量
sdasd局部变量表的容量:以变量槽(Variable Slot) 为最小单位。
sdasdJVM通过索引定位的方式使用局部变量表,索引值的范围是从0开始。但是比如我们访问的是32位数据类型的变量,那么索引N就代表第N个槽(第0个存储的是this,是对当前方法所属对象实例的引用)
sdasd当一个方法被调用时,Java虚拟机会使用局部变量表来完成参数值到参数变量列表的传递过程,即实参到形参的传递。
sdd【注】: 在《Java虚拟机规范》中并没有明确指出一个变量槽应占用的内存空间大小,但是指明每个槽能存放一个boolean、byte、char、short、int、float、reference或returnAddress类型的数据,而这这数据的类型最大为32位。所以我们可以等价认为每个槽占用的内存空间长度至少为32位(保证了即使在64位虚拟机中使用了64位的物理内存空间去实现一个变量槽,虚拟机仍要使用对齐和补白的手段让变量槽在外观上看起来与32位虚拟机中的一致)。
sdsssssssdreference类型:表示对一个对象实例的引用,其实在《Java虚拟机规范》中并没有规定它的长度以及结构(它的长度与实际使用32位还是64位虚拟机有关,如果是64位虚拟机,还与是否开启某些对象指针压缩的优化有关,这里我们暂且只取32位虚拟机的reference)。但是它要实现两个功能:①、根据引用可以直接或间接地查找到对象在Java堆中的数据存放的起始地址或索引。二是根据引用直接或者间接的查找到对象所属数据类型在方法区中的存储的类型信息。
sdsssssssdreturnAddress类型:目前基本不用,它是为字节码指令jsr、jsr_w和ret服务的,指向了一条字节码指令的地址,通常用来实现异常的处理的跳转,但是现在已经采用 异常表 来代替了。
sdsssssssd对于64位的数据类型,Java虚拟机会以高位对齐的方式为其分配两个连续的变量槽空间。无论读写两个连续的变量槽是否为原子操作,都不会引起数据竞争和线程安全问题,因为局部变量表是线程私有的。并且只能同时访问这两个连续槽,否则在类加载的校验阶段会抛出异常。
sdd
局部变量表的优化
sdd
sdasd为了尽可能节省栈帧耗用的内存空间,局部变量表中的变量槽是可以 重用,在方法体中定义的常量,其作用域并不一定会覆盖整个方法,如果当前字节码的PC计数器的值已经超出了某个局部变量的作用域,那这个局部变量所用的槽就可以被重新利用了。虽然这样能节省栈帧空间,但是也会产生一些副作用,比如gc。
sdasd例子:

public static void main(String[] args)() {
    1
	byte[] placeholder = new byte[64 * 1024 * 1024];
	System.gc();							结果显示没有回收
}
public static void main(String[] args)() {
    2
	{
    
		byte[] placeholder = new byte[64 * 1024 * 1024];
	}
	System.gc();						   结果显示没有回收
}
public static void main(String[] args)() {
    3
{
    
	byte[] placeholder = new byte[64 * 1024 * 1024];
}
	int a = 0;
	System.gc();						   结果显示已经回收
}

sdasd分析:例1没有回收可以理解,是因为还在作用域范围内,但是例2没有回收是因为什么呢,gc时它的作用域已经结束了,但是它的引用还在局部变量中,而在这一段时间并没有对局部变量表的一个读写操作,所以没有发现它(placeholder)已经无用,可以gc了,因此我们在例3中通过设置a=0,让其对局部变量表进行访问,从而可以在gc的时候对它进行回收。但是这只是概念模型中的应用,在实际执行中其实完全不是这样的,这也是所谓的"共有设计,私有实现",外部看起来等效,但是内部已经差别很大,因为VM使用解释器执行时,和概念模型是接近的,但是经过即时编译器(JIT)各种优化后,两者的差异就非常大了。而在JIT的作用下例1也会发生gc。


操作数栈
sdd
sdasd操作数栈,也称为"操作栈",是一个先入后出的栈。
sdasd和局部变量表一样,操作数栈的最大深度在编译的时候就会被写入到 Code属性的max_stacks数据项 之中。
sdasd操作数栈的每一个元素都可以包含long,double在内的任何数据类型,32位数据类型所占的栈容量为1,64位的栈容量为2。
sdasd在概念模型中,两个不同的栈帧作为不同方法的虚拟机栈的元素,是相互独立的。
sdasdJava虚拟机的解释执行引擎被称为“基于栈的执行引擎”,里面的“栈”就是操作数栈。
sdd
操作数栈的优化(不太理解)
sdd
sdasd在大多虚拟机的实现里都会进行一些优化处理,令两个栈帧出现一部分重叠。让下面栈帧的部分操作数栈与上面栈帧的部分局部变量表重叠在一起,这样做不仅节约了一些空间,更重要的是在进行方法调用时就可以直接共用一部分数据,无须进行额外的参数复制传递,如图:
在这里插入图片描述


动态连接
sdd
sdasd每个栈帧包含一个 指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接
sdasdClass文件的常量池中存有大量的符号引用,字节码的方法调用指令就以常量池里指向方法的符号引用作为参数。这些符号引用分为两部分:
sasdasddasd①、静态解析: 一部分符号引用在类加载阶段或者第一次使用的时候被转化为直接引用。
sasdasddasd②、动态解析: 在每一次运行期间都转换为直接引用。


方法返回地址
sdd
sdasd当一个方法开始执行后,只有两种方式退出这个方法:
sdasadsadsd①、正常调用完成: 执行引擎遇到任意一个方法返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者。
sdasadsadsd②、异常调用完成: 是在方法执行的过程中遇到了异常,并且在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出。Completion)”。一个方法使用异常完成出口的方式退出,是不会给它的上层调用者提供任何返回值的
sdd【注】: 无论采用何种退出方式,在方法退出之后,都必须返回到最初方法被调用时的位置。方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它的上层主调方法的执行状态。
ssasadsadd方法正常退出时, 主调方法的PC计数器的值就可以作为返回地址,栈帧中很可能会保存这个计数器值。
ssasadsadd而方法异常退出时,返回地址是要通过异常处理器表来确定的,栈帧中就一般不会保存这部分信息。
ssasadsadd方法退出的过程实际上等同于把当前栈帧出栈,因此退出时可能(基于概念模型的分析) 执行的操作有:①、恢复上层方法的局部变量表和操作数栈,②、把返回值(如果有的话)压入调用者栈帧的操作数栈中;③、调整PC计数器的值以指向方法调用指令后面的一条指令等


附加信息
sdd
sdasd:《Java虚拟机规范》允许虚拟机实现增加一些规范里没有描述的信息到栈帧之中,例如与调试、性能收集相关的信息,这部分信息完全取决于具体的虚拟机实现。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wwj17647590781/article/details/118957845

智能推荐

RadStudio 10.3.3 Rio (Delphi & C++ Builder)及TMS TAdvStringGrid控件安装方法_rad studio 10.3.3 注册码-程序员宅基地

文章浏览阅读4.2k次。目录RadStudio下载及安装TMS Component Pack安装方法安装TMS VCL UI PackRadStudio下载及安装下载地址:https://altd.embarcadero.com/download/radstudio/10.3/delphicbuilder10_3_3_7899_nt.iso注意事项:若下载速度很慢,例如几十kb/s,可尝试在早上7点左右下载,速度..._rad studio 10.3.3 注册码

[OpenCV实战]51 基于OpenCV实现图像极坐标变换与逆变换_opencv坐标系转换-程序员宅基地

文章浏览阅读6.2k次,点赞11次,收藏82次。在图像处理领域中,经常通过极坐标与笛卡尔直角坐标的互转来实现图像中圆形转为方形,或者通过极坐标反变换实现方形转圆形。例如钟表的表盘,人眼虹膜,医学血管断层都需要用到极坐标变换来实现圆转方。文章目录1 基础数学知识1.1 极坐标1.2 二维直角坐标系转换2 圆形区域转换为矩形区域2.1 预设值2.2 标准圆形转换2.2.1 Step1 获得各点的极坐标2.2.2 Step2 获得直角坐标2.2.3 Step3 获得OpenCV图像坐标2.2.4 示例代码2.3 任意角度圆形转换2.4 任意角度圆形顺时针转换_opencv坐标系转换

《C》C语言编程实现指定阶“m序列”并通过gnuplot绘图_c语言编写m序列-程序员宅基地

文章浏览阅读2.5k次,点赞6次,收藏20次。一、怎么构建m序列    m序列是一种基本的伪随机序列,有优良的自相关函数,易于产生和复制,在扩频技术中得到了广泛的应用。长度为 位的m序列可以用n级线性移位寄存器来产生。如下图所示:将发生器写成如下方程:f(x)=C0+C1x+C2x2+...+Cnxn=∑i=0nCixif(x)=C_0+C_1x+C_2x^2+...+C_nx^n=\sum_{i=0}^nC_ix^if(x)=C0​..._c语言编写m序列

springcloud五大神兽之Gateway_springcloud五大组件 gateway-程序员宅基地

文章浏览阅读174次。① 什么是网关?API 网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 API 网关这一层。网关的出现原因是伴随微服务架构的出现而出现,因为不同的微服务一般有不同的网络地址(ip+port),但客户端的一个请求可能需要多个微服务的接口互调才可以实现。它是Spring Cloud团队的一个全新项目,基于Spring 5.0、SpringBoot2.0、Project Reactor 等技术开发的网关。 旨在为微服务架构提供一种简单、有效、统一的API路由管理方式。目标是替代Netfl_springcloud五大组件 gateway

上滑吸顶功能_taro onpagescroll-程序员宅基地

文章浏览阅读1.5k次。功能描述:当页面上滑到导航时,导航吸顶解决思路:利用onPageScroll函数来监听页面上滑的距离,然后绑定数据,改变导航栏的样式onPageScroll = (e) => { let menuTop = 87; //当距离不确定时,可以用createSelectorQuery来测量 if (e.scrollTop > menuTop)..._taro onpagescroll

金仓数据库 KingbaseES 插件参考手册 S (2)_金仓数据库提示模式“anon"是什么-程序员宅基地

文章浏览阅读497次。sys_anon是KingbaseES的一个扩展插件,主要用于支持数据脱敏功能。数据脱敏,指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。具体参考《KingbaseES安全指南》第10章数据脱敏。插件名为 sys_anon插件版本 V1.0sys_audlog 是一个 Kingbase 的扩展,可以实现帐户异常登录锁定以及账户登录信息显示。这种方式更为灵活,当数据库的实用场景需要进行帐户异常登录锁定以及账户登录信息显示时,加载插件即可。而不需要该功能时,卸载插件即可。..._金仓数据库提示模式“anon"是什么

随便推点

adobe acrobat pro dc 更新后正常体验使用_isamtenforced-程序员宅基地

文章浏览阅读2.3k次。adobe acrobat pro dc 更新后破解失效怎么解决?文章整理来源于网络,仅供参考和个人学习。[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Adobe\Adobe Acrobat\DC\Activation]“IsAMTEnforced”=dword:00000001注册表新增这个键值dword32类型,数值1。然后重新用AMTEmu0.9.2激活就行了AMT Emulator 0.9.2.exe 工具:链接:https://pan.baid_isamtenforced

k8s使用port-forward访问集群中的应用程序(只能在执行命令的机器上开放端口)_svc port-forward-程序员宅基地

文章浏览阅读2.4k次。k8s使用port-forward访问集群中的应用程序本文描述了如何使用 kubectl port-forward 访问 Kubernetes 集群中的 Redis Server。这种连接方式在实际进行Debug时非常有效。为Redis创建Deployment和Service转发本地端口到Pod的端口总结为Redis创建Deployment和Service创建 Redis Deployment,YAML文件如下:apiVersion: apps/v1kind: Deployment_svc port-forward

记一次关于Fragment的内存泄漏_madded in fragmentstore 内存泄露-程序员宅基地

文章浏览阅读1.2w次,点赞3次,收藏4次。之前使用单Activity多Fragment架构完成过一个项目,在后期维护时发现一个很严重的问题,很多页面在关闭之后,内存无法被回收,出现了内存泄漏问题。leakcanary显示信息如下:..._madded in fragmentstore 内存泄露

YUV420P格式图像处理分割,复制,合并_两个yuv420p进行合成一个-程序员宅基地

文章浏览阅读8.8k次,点赞2次,收藏19次。首先说明下yuv420的格式下面选自http://blog.csdn.net/jefry_xdz/article/details/7931018提示: 读下面的文字时,希望大家结合图片看,这样更易理解 在YUV420中,一个像素点对应一个Y,一个2X2的小方块对应一个U和V。对于所有YUV420图像,它们的Y值排列是完全相同的,因为只有Y的图像就是灰度图像。YUV420sp_两个yuv420p进行合成一个

Hackthebox-Bart(考点:信息搜集/密码猜解/user-agent注入/window账号利用)_htb bart-程序员宅基地

文章浏览阅读716次。nmap搞起显示forum.htb,恩,加到/etc/host 里去 10.10.10.81 forum.htb就一个80端口,进去看看网页,没啥,ctrl+u看网页源码有他们好几个员工的邮箱,这些可以用来做登录信息,但是现在还没发现哪里登录于是,搜起,过程很慢,搜到monitor进去就是登录框,可以试试那几个员工信息,在forget passwords里,随便输入个,当然不行..._htb bart

Centos7--EFK监控nginx日志-程序员宅基地

文章浏览阅读252次。主: 192.168.227.170 从: 192.168.227.171 从: 192.168.227.173 三台都安装zookeeper和kafka 时间同步 修改主机名 三台都配置/etc/hosts文件 测试能否ping通 1...._efk监控nginx

推荐文章

热门文章

相关标签