前置知识

阅读本文需要对以下知识有所了解:

* 栈

* 汇编

* Java 基础

* 逆波兰表达式(有学过的同学阅读本文毫无障碍)

引子

基于寄存器的设计模式

就我们所熟知的x86或arm指令集来说,其对数据的操作都是基于寄存器。例如,要对两个数执行加法操作则需要将这两个数分别送入两个寄存器再执行加法操作,这也符合我们对于编程语言认知,更加易于理解。

基于栈的设计模式

基于栈的设计模式则是将数据存放在栈中,在需要使用的时候将栈顶的数据出栈,并执行相应的操作。

举例来说,在JVM中 执行 a = b + c 的字节码执行过程中操作数栈以及局部变量表的变化如下图所示。

局部变量表中存储着a、b、c 三个局部变量,首先将b和c分别入栈

将栈顶的两个数出栈执行加法操作,并将结果保存至栈顶,之后将栈顶的数出栈赋值给a

一个简单的例子

在上一节中我们了解了栈与局部变量表是如何配合完成一次加法操作的,这一节我们将对局部变量表进行深入的研究。

如何查看局部变量表?

我们可以通过反编译class文件的方式查看局部变量表,不过在这里更加推荐使用IDEA的jclasslib插件(直接搜就有)查看字节码,因为其设计更加人性化,更加友好。

实例方法中的局部变量表

我们知道在实例方法中我们可以直接访问实例的成员变量或函数,而不需要通过this来引用,这是如何实现的?

像这种问题直接动手写个测试类,反编译一下结果自然就清晰了。

首先来一个简单的类

public class T {

    private int a = 0;

    public void add(int b,int c){
a = b + c;
}
}

其次,将该类选中,然后在view中选中showbytecode with jclasslib

效果如下:

选择我们关注的Methods中add方法,注意观察图中高亮的部分

原来,JVM在编译代码的时候,偷偷在局部变量表中添加了一个this引用(很明显this保存的实例的引用),这也是我们为什么可以在方法中访问实例中的成员变量的原因,证明如下

图中节码的简要解释如下:

0)aload_0 将this的引用入栈 (aload_0即将局部变量表中索引为0的引用压到操作数栈中)

1)iload_1 将参数b入栈 (将局部变量中的索引为1的整数压到操作数栈中)

2)iload_2 将参数c入栈

此时栈的内容有(0为栈顶)

0.c

1.b

2.this

3)iadd 将栈顶的两个数相加,并将结果保存至栈顶,此时栈的内容为

0.b+c

1.this

4). putfield 将栈顶的两个值出栈,第一个值(b+c)赋值给第二个值(this)的对应的成员变量(是的,没错即使是赋值也要执行两次出栈操作)

putfield的说明如下(注意图中的高亮部分):



地址:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.putfield

结论

基于栈的指令集系统可以很方便的做到平台无关性(x86、arm),但也降低了性能,这也是为啥Java性能比C低原因。(操作寄存器快,还是操作栈快?哈哈哈哈哈哈哈哈哈哈哈)

JVM 栈帧之操作数栈与局部变量表的更多相关文章

  1. 四、JVM之栈与栈帧

    栈: 1.又名堆栈,它是一种运算受限的线性表.其限制是仅允许在表的一端进行插入和删除运算.这一端被称为栈顶,相对地,把 另一端称为栈底.其特性是先进后出. 2.栈是线程私有的,生命周期跟线程相同,当创 ...

  2. 栈帧的内部结构--操作数栈(Opreand Stack)

    每个栈帧中包含: 局部变量表(Local Variables) 操作数栈(Opreand Stack) 或表达式栈 动态链接 (Dynamic Linking) (或指向运行时常量的方法引用) 动态返 ...

  3. 【死磕JVM】一道面试题引发的“栈帧”!!!

    前言 最近小农的朋友--小勇在找工作,开年来金三银四,都想跳一跳,找个踏(gao)实(xin)点的工作,这不小勇也去面试了,不得不说,现在面试,各种底层各种原理,层出不穷,小勇就遇上了这么一道面试题, ...

  4. 图解JVM字节码执行引擎之栈帧结构

    一.执行引擎      “虚拟机”的概念是相对于“物理机”而言的,这两种“机器”都有执行代码的能力.物理机的执行引擎是直接建立在硬件处理器.物理寄存器.指令集和操作系统层面的:而“虚拟机”的执行引擎是 ...

  5. JAVA栈帧

    简介 Java栈是一块线程私有的内存空间.java堆和程序数据相关,java栈就是和线程执行密切相关的,线程的执行的基本行为是函数调用,每次函数调用的数据都是通过java栈来传递的. Java栈与数据 ...

  6. Java虚拟机之栈帧

    写在前面的话:Java虚拟机是一门学问,是众多Java大神们的杰作,由于我个人水平有限,精力有限,不能保证所有的东西都是正确的,这里内容都是经过深思熟虑的,部分引用原著的内容,讲的已经很好了,不在累述 ...

  7. java 栈和栈帧

    文章转载自:http://www.tuicool.com/articles/URZrMnb jvm为每个新创建的线程都分配一个堆栈.堆栈以帧为单位保存线程的状态.jvm对堆栈只进行两种操作:以帧为单位 ...

  8. java虚拟机规范-运行时栈帧

    前言 java虚拟机是java跨平台的基石,本文的描述以jdk7.0为准,其他版本可能会有一些微调. 引用 java虚拟机规范 java虚拟机规范-运行时数据区 java内存运行时的栈帧结构 java ...

  9. 详细解析Java虚拟机的栈帧结构

    欢迎关注微信公众号:万猫学社,每周一分享Java技术干货. 什么是栈帧? 正如大家所了解的,Java虚拟机的内存区域被划分为程序计数器.虚拟机栈.本地方法栈.堆和方法区.(什么?你还不知道,赶紧去看看 ...

随机推荐

  1. 常见Code Review过程中发现的问题

    软件环境:Spring MVC + MyBatis 主要体现在两个方面,一个是编码习惯问题,另一个是编码质量的问题.编码习惯主要有日志编写.代码注释以及编码风格的问题,而编码质量则与很多方面相关,比如 ...

  2. shell脚本常见错误一二三

    1.$'\r': 未找到命令的解决 2.: 不是有效的标识符h: 3.cd "$path"/webapps/ROOT 不能正常进入ROOT文件夹,$path并未与后面的字符结合起来 ...

  3. linux字符设备驱动--基本知识介绍

    一.设备驱动的分类 1.字符设备 字符设备是指那些能一个字节一个字节读取数据的设备,如LED灯.键盘.鼠标等.字符设备一般需要在驱动层实现open().close().read().write().i ...

  4. 7月18日刷题记录 二分答案跳石头游戏Getting

    通过数:1 明天就要暑假编程集训啦~莫名开心 今天做出了一道 二分答案题(好艰辛鸭) 1049: B13-二分-跳石头游戏(二分答案) 时间限制: 5 Sec  内存限制: 256 MB提交: 30  ...

  5. 【模拟】(正解树状数组)-校长的问题-C++-计蒜客

    描述 学校中有 n 名学生,学号分别为 1 - n.再一次考试过后,学校按照学生的分数排了一个名次(分数一样,按照名字的字典序排序).你是一名老师,你明天要和校长汇报这次考试的考试情况,校长询问的方式 ...

  6. Java项目案例之---登录和修改(JSP)

    登录和修改(JSP) 通过案例学习jsp的常用知识点: 1.创建一个Map集合,用于存放学生信息,将学生信息存入Map中 2.通过page将需要的包导入 3.用request.getParameter ...

  7. python -服务器与客户端断电续传程序详细介绍

    6.28自我总结 客户端与服务器之间文件传输断电续传 `通过判断文件大小,以及文件在读取中的指针位置的调整来解决断电续传问题' 1.程序目录 E:/断电续传 |___bil | |___common. ...

  8. 知识图谱学习与实践(4)——通过例句介绍Sparql的使用

    通过例句介绍Sparql的使用 1 简介 SPARQL的定义,是一个递归的定义,为SPARQL Protocal and RDF Query Language,是W3C制定的RDF知识图谱标准查询语言 ...

  9. 【git】Git的使用

    一.安装git 1.windows下安装一个Git 2.lInux下yum(apt-get) install git 二.使用git连接github 使用git连接github时,需要将linux下产 ...

  10. Gordon家族(一)

    引子 Go语言的吉祥物是一只囊地鼠(gopher),由插画师Renee French设计,名叫Gordon,长得这个样子: 在Go官网上(https://golang.google.cn/)的Gord ...