JVM007_运行时栈帧结构

运行时栈帧结构

执行引擎是JVM的核心组件之一。
所有Java虚拟机的执行引擎输入输出都是一致的:输入的是字节码二进制流,处理过程是字节码解析执行的等效过程,输出的是执行结果。

JVM以方法作为作基本的执行单元。“栈帧”是用于支持虚拟机进行方法调用和方法执行背后的数据结构。这里的方法调用指的是确定调用那一个方法,也是JVM运行时数据区中栈的栈元素。栈帧存储的内容主要有:局部变量表,操作数栈,动态连接和方法返回地址信息等。

局部变量表

局部变量表是一组变量的存储空间。用以存储方法参数和方法内的局部变量。在编译时其最大容量就被确定下来,并被写到方法的Code属性中的max_locals数据项中。

局部便量表的容量以变量槽为单位。在《JVM规范》中并没有明确的指定一个槽占用的内存的大小为多少,而是导向性的说:每个变量槽都应该能存放一个char,boolean,short,int,byte,float,reference,returnAddress数据类型。这八个数据类型都可以用32位或者更少的物理内存来存储。这意味着一个变量槽所占用的物理内存可以随着处理器、操作系统或者虚拟机实现的不同而发生变化,只是变量槽的外观与32位虚拟机一致。
下面的讨论如果涉及到变量槽没有特殊说明那么都是基于32位虚拟机
reference类型一般需要满足两个条件:
1. 通过该引用能够直接或间接的查找到对象在Java堆中的数据存放的起始地质或索引。
2. 通过该引用能够直接或间接地查找到该对象对应的数据类型在方法区中的存储的类型信息。
returnAddress目前很少见了,用来为字节码指令jsr,jsr_w,ret服务的,指向一条字节码指令的地址,在一些古老的虚拟机中用来实现异常处理时的跳转,目前都是用异常表来处理异常的。
对于long,double这两种64位的数据类型,需要两个变量槽来表示。由于局部变量表是建立在线程内,且对其他线程是不可见的,所以不会存在数据竞争和线程安全问题。对于相邻的共同存放一个64位数据结构的变量,虚拟机不允许采取任何方式独立访问其中一个变量槽。若遇到就抛出异常。

当一个方法调用时,若方法不是静态方法,那边变量槽第一个槽中会存放所属对象的引用,也就是this。变量槽是可以被复用的,当一个变量槽中的变量在字节码执行超过其范围后,就可以被复用。

操作数栈

操作数栈也被称为操作栈,是一个先入后出的栈。Java虚拟机的解释执行引擎被称为”基于栈的执行引擎“,这里的栈指的就是操作数栈。操作数栈的最大深度在Javac编译器编译时便确定了,并写入到Code属性的max_stacks数据项。当操作数栈的元素是long或double的时候,那么一个数据占用两个栈容量。Javac编译器的数据流分析工作保证了方法在执行的时候,任何是首操作数栈的深度都不会超过max_stacks的值。操作数栈中的数据类型必须与字节码指令的序列严格匹配。

在大多数的虚拟机的实现中,会对栈帧作出一些优化:让下面栈帧的部分操作数栈与上面栈帧的局部变量部分重叠在一起,以节约空间并且在进行方法调用时就可以直接共用一部分数据,无须额外的参数复制传递。

动态连接

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

动态连接是指Calss文件常量池中的不在类加载阶段和不在第一次使用就转换为直接引用的符号引用,而是在每一次运行期间都转换为直接引用。

方法返回地址

方法在退出的时候,需要返回到最初被调用的位置,程序才能继续执行,方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它上层主调方法的执行状态。一般来说法方法正常推出时,主调方法的PC计数器的值可以作为方法返回地址。而方法异常退出时,返回地址是通过异常处理表来确定的,栈帧中不会保存这部分信息。

关于退出,即推出方法的方式,可以分为“正常调用完成”和”异常调用完成“。正常调用完成指的时执行引擎遇到一个方法返回的字节码指令,退出方法。这里的方法字节码返回指令决定了方法返回是否有返回值传递给上层的方法调用者。异常调用完成指的是方法在执行过程中遇到异常(JVM内部产生的、代码中athrow指令禅寺的),只要在本方法的异常表中没有匹配的异常处理器,就会导致方法退出。
方法的退出等同于当前栈帧的出栈,所以可能存在的操作有:1.恢复上层方法的局部变量表和操作数栈 2若有返回值,将返回值压入到调用者栈帧的操作数栈中 3调整PC计数器的值以指向方法调用指令后面的一条指令等。

附加信息

一些《JVM规范》中没有描述的信息,例如与调试、性能收集有关的信息。

ubuntu系统弄得,不知道为什么格式不对

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

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

相关文章

Shiro————核心设计思想

引言 以此篇博客为引,开启一个新的专栏分类——Shiro。 之前在工作中有比较快速的学习过Shiro安全框架,但经过一年的荒废,已经不是很熟悉了,通过这个系列,深入研究和学习Shiro的一些知识,填补安全管理方面…

Web应用安全————账号冻结与 Session 实时失效

引言 开篇时说些题外话,最近刚刚被公司CY,不过很快找到了下家,也同时拿到了三家公司的Offer。一周面试下来,总体感觉面试题少了,不过多了上机程序题。新公司是做外包,不过相比于上一家公司,也算…

Web应用安全————Shiro 解决会话固定漏洞

引言 承接上一篇《Web应用安全————账号冻结与 Session 实时失效》关于 session 的学习,本篇博客聚焦如何通过 shiro 解决会话固定导致的漏洞问题。 首先,没怎么接触过应用安全方面的小伙伴可能会发起疑问 - 什么是会话固定? 简单来说&…

Web应用安全————多点登录互斥

引言 在实际生活中,很多网站都做了多点登录互斥的操作,简单来说就是同一个账号,只能在一台电脑上登录,如果有人在其他地方登录,那么原来登录的地方就会自动下线,再进行操作就会弹出登录界面。 实现思路 …

Shiro————会话管理

引言 本篇博客翻译自Shiro 官方网站的 Session Manager 手册。 网页地址:http://shiro.apache.org/session-management.html Shiro 会话管理支持的特性 基于POJO/J2SE(IoC容器友好的)- Shiro 中的所有东西都是基于接口的,而且…

Linux进阶之路————磁盘查询

引言 承接《Linux进阶之路————Linux磁盘分区与挂载》,本文介绍实际生产中对于磁盘的监控和查询。 一、查询磁盘整体使用情况 基本语法: df -h 该命令会显示包括我们手动挂载的磁盘,如果使用 umount 卸载磁盘,那么将不会显示…

Linux进阶之路————CentOS网络配置

引言 Linux在装机后,如果没有特殊配置,会使用动态获取 IP 地址的策略。本文描述了,虚拟机使用网络的拓扑图,以及如何通过配置,将 IP 地址固定下来,不会因为重启而失效。同时可以访问外网地址。 一、NAT模…

Linux进阶之路————进程与服务管理

引言 在Linux 中,每个执行的程序(代码)都成为一个进程,Linux 为每一个进程分配了一个唯一的 id 号 - PID。 每个进程都会对应一个父进程,而这个父进程可以复制多个子进程,例如 www 服务器。 每个进程都可…

Linux进阶之路———— RPM 与 YUM 包管理

引言 rpm 是一种用于互联网下载的打包及安装工具,它包含在某些 Linux 发行版中,生成具有 .rpm 扩展名的文件。rpm 是 redhat package manager(RedHat 软件包管理器)的缩写,类似 Windows 下的 setup.exe 文件。这一文件…

Linux进阶之路———Shell 编程入门

引言 通过 Shell 编程的学习,铺平架构师道路上的一块大砖。 Shell 在Linux 系统中的定位如下所示: 一、第一个 Shell 脚本 我们通过一个简单的 Shell 脚本来感受一下。 在 Shell 中不需要加 “;” 结尾,通过 vim 可以进行 shell 的编程工…

Linux 实操———CentOS 6 安装配置 Oracle JDK 1.8

引言 本篇博客也属于Linux进阶系列,主要讲解如何在CentOS 6 下安装并配置 JDK 8。由于通过 yum 搜索的结果都是 openjdk,而目前企业中还是以 Oracle jdk 为主,因此,操作步骤这样的。 在Oracle 官网把 jdk 1.8 下载下来&#xff…

Linux 实操———CentOS 6 安装配置 Tomcat

引言 Linux下安装Tomcat。 一、下载、传输与解压 同《Linux 实操———CentOS 6 安装配置 Oracle JDK 1.8》一样,前期都是先在远程机上下载压缩包,然后通过远程终端,将压缩包放在 Linux 的 opt 目录下,然后解压。 下载地址是T…

Spring Boot 实用开发技巧————Eclipse 远程调试

引言 在之前的开发当中,都会进行本地项目启动,然后向本地服务发起请求来进行 Debug 调试代码,这也是开发人员最常见的调试操作。但是当项目逐渐成型,慢慢的将各个模块部署到服务器后,调试的手段可能就仅仅剩下查看执行…

Linux 实操———— Shell 远程执行命令

引言 目前,开发人员的部署方式是,将项目打包(Maven 打包) 然后将 生成的 jar 包等文件,通过Xshell 等终端工具手动传输到远程服务器上,然后再通过在终端执行远程服务器上的 shell 脚本来启动服务。 本篇博客聚焦这样一种解决方案…

Spring Boot 设置 ASCII banner 艺术字

引言 无意中看到Spring boot 项目的 resources 目录下有一个 banner.txt ,打开一看,居然是ASCII 字符画。于是兴起,简单研究了一下。 Spring boot 可以加载 resources 目录下的 banner.txt 文件,将字符画在启动之初输出到日志或…

MySQL 基础 ———— 分组查询

引言 承接上一篇《MySQL 基础 ————高频函数总结》,本篇单独针对分组查询进行简单的总结和归纳,并为后续更为复杂的DQL 语句做好铺垫。 查询语句: SELECT AVG(salary) FROM teacher; 实际上是以全表的 salary 字段来求平均值。但是在实…

MySQL 基础 ———— 连接查询

引言 本篇文章承接《数据库与SQL语句》专栏,进入DQL的重要环节,可以说,这一部分的内容应该占据SQL语言的大部分使用场景。 本篇的连接查询知识,和后面的一些重要的查询知识总结,共同构成了在工作中80%的MySQL应用场景…

MySQL 基础 ———— 子查询

引言 承接《MySQL 基础 ———— 连接查询》,本文介绍和展示SQL中子查询的使用。 子查询是出现在其他语句中的select 语句,也称为内查询。外部的查询语句,称为主查询或外查询。 一、子查询的分类和支持的子句 按照子查询出现的位置&#…

MySQL 基础 ———— SQL语句的执行顺序与 LIMIT 子句

引言 到目前为止,已经总结了常见的SQL子句,包括 SELECT 、FROM、JOIN ... ON、WHERE、GROUP BY、HAVING、ORDER BY。 虽然SQL的书写顺序是固定的,但在MySQL引擎中执行的顺序并不完全和书写顺序一致。除了上述这些子句,下面将会介…

MySQL 基础———— UNION 联合查询

引言 联合查询与连接查询不同,通过UNION 关键字,我们可以将多个查询语句一同执行并将结果集展示出来,不涉及到任何关联关系。 UNION 的含义是“联合,并集,结合”,在MySQL中可以将多个查询语句的结果合并成…