前置知识

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

* 栈

* 汇编

* 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. spark 源码分析之十四 -- broadcast 是如何实现的?

    本篇文章主要剖析broadcast 的实现机制. BroadcastManager初始化 BroadcastManager初始化方法源码如下: TorrentBroadcastFactory的继承关系 ...

  2. Java编程思想:内部类基础部分

    public class Test { public static void main(String[] args) { // Parcel1.test(); // Parcel2.test(); / ...

  3. vim 复制大块内容。 y,p(是单个y,而不是yy)

    vim 复制大块内容. y,p(是单个y,而不是yy)

  4. 洛谷 P3367 并查集 【模板题】

    题目描述 如题,现在有一个并查集,你需要完成合并和查询操作. 输入输出格式 输入格式: 第一行包含两个整数N.M,表示共有N个元素和M个操作. 接下来M行,每行包含三个整数Zi.Xi.Yi 当Zi=1 ...

  5. 【CYH-02】NOIp考砸后虐题赛:函数:题解

    这道题貌似只有@AKEE 大佬A掉,恭喜! 还有因为c++中支持两个参数数量不同的相同名称的函数调用,所以当时就没改成两个函数,这里表示抱歉. 这道题可直接用指针+hash一下,然后就模拟即可. 代码 ...

  6. K2 smarforms 控件整理

    K2 Community – Market – Smatform Controls l   K2 blackpearl 1.    Drag and Drop Upload Control http: ...

  7. python课堂整理15---map, filter,reduce函数

    一.map函数 处理序列(可迭代对象)中的每一个元素,得到的结果是一个‘列表’(其实是个迭代器),该‘列表’元素个数及位置与原来一样 理解下面这段代码: num_l = [1, 2, 4, 6] de ...

  8. opencv编译

    1. clone源码 https://github.com/opencv/opencv 2. 安装cmake 3. cmake配置的时候,输出目录需要另外设置一个目录,不可以放到源码目录 4. 用cm ...

  9. java - java集合类

    1.接口实现类 ①List List list1 = new ArrayList(); List list2 = new LinkedList(); ②Set Set<String> se ...

  10. 仿制shazzam的简单功能,将hlsl转换为WPF中的ShaderEffect

    (此文章只是在对WPF的Effect产生兴趣才稍微研究了一点后面的知识;需要了解更多可参考https://archive.codeplex.com/?p=shazzam的源代码以及WPF基础知识) 1 ...