关于jvm的栈和帧栈理解

参考
https://blog.csdn.net/jiasanshou/article/details/7007806

Java中的栈

每当启用一个线程时,JVM就为他分配一个Java栈,栈是以帧为单位保存当前线程的运行状态。某个线程正在执行的方法称为当前方法,当前方法使用的栈帧称为当前帧,当前方法所属的类称为当前类,当前类的常量池称为当前常量池。当线程执行一个方法时,它会跟踪当前常量池。
每当线程调用一个Java方法时,JVM就会在该线程对应的栈中压入一个帧,这个帧自然就成了当前帧。当执行这个方法时,它使用这个帧来存储参数、局部变量、中间运算结果等等。
Java栈上的所有数据都是私有的。任何线程都不能访问另一个线程的栈数据。所以我们不用考虑多线程情况下栈数据访问同步的情况。
关于线程共享,先简单引入一图
这里写图片描述
此处虚拟机栈即为本文所提的栈本地方法栈??还未在此区分,需要一会儿再看”

回到帧栈

Java栈的组成元素——栈帧

栈帧由三部分组成:局部变量区、操作数栈、帧数据区。局部变量区和操作数栈的大小要视对应的方法而定,他们是按字长(在同一时间中处理二进制数的位数叫字长。大型计算机的字长为32―64位)计算的。但调用一个方法时,它从类型信息中得到此方法局部变量区和操作数栈大小,并据此分配栈内存,然后压入Java栈。

  • 局部变量区
    局部变量区被组织为以一个字长为单位、从0开始计数的数组,类型为short、byte和char的值在存入数组前要被转换成int值,而long和double在数组中占据连续的两项,在访问局部变量中的long或double时,只需取出连续两项的第一项的索引值即可,如某个long值在局部变量区中占据的索引时3、4项,取值时,指令只需取索引为3的long值即可。

    下面就看个例子,好让大家对局部变量区有更深刻的认识。这个图来自《深入JVM》:

public static int runClassMethod(int i,long l,float f,double d,Object o,byte b) {     
        return 0;     
    }     

    public int runInstanceMethod(char c,double d,short s,boolean b) {     
        return 0;     
    }    

上面代码片的方法参数和局部变量在局部变量区中的存储结构如下图:
这里写图片描述
体现出:
调用一个方法时,它从类型信息中得到此方法局部变量区和操作数栈大小,并据此分配栈内存
要注意:
runInstanceMethod的局部变量区第一项是个reference(引用),它指定的就是对象本身的引用,也就是我们常用的this,但是在runClassMethod方法中,没这个引用,那是因为runClassMethod是个静态方法。调用静态方法不需要实例化对象,所以没this这个引用

  • 操作数栈
    操作数栈也被组织成一个以字长为单位的数组。但和前者不同的是,它不是通过索引(索引是相对于数组而言的,而不是说全都是引用,可能帧栈的局部变量是带有索引的数组堆栈的??关于数组??)来访问的,而是通过入栈和出栈来访问的。可把操作数栈理解为存储计算时,临时数据的存储区域。下面我们通过一段简短的程序片段外加一幅图片来了解下操作数栈的作用。
int a = 100;
int b = 98;
int c = a+b;
字节码序列:
iload_0 //入栈
iload_1 //入栈
iadd //弹出2个栈中数据相加后,把结果入栈
istore_2 //弹出结果存储到局部变量中位置2处

这里写图片描述

从图中可以得出:操作数栈其实就是个临时数据存储区域,它是通过入栈和出栈来进行操作的。

  • 帧数据区
    Java栈帧还需要一些数据来支持常量池解析、正常方法返回以及异常派发机制。这些数据都保存在Java栈帧的帧数据区中。
    当JVM执行到需要常量池数据的指令时,它都会通过帧数据区中指向常量池的指针来访问它。此处还需要学习??
    除了处理常量池解析外,帧里的数据还要处理Java方法的正常结束和异常终止。如果是通过return正常结束,则当前栈帧从Java栈中弹出,恢复发起调用的方法的栈。如果方法又返回值,JVM会把返回值压入到发起调用方法的操作数栈。此处还需要学习??
    为了处理Java方法中的异常情况,帧数据区还必须保存一个对此方法异常引用表的引用。当异常抛出时,JVM给catch块中的代码。如果没发现,方法立即终止,然后JVM用帧区数据的信息恢复发起调用的方法的帧。然后再发起调用方法的上下文重新抛出同样的异常。此处还需要学习??

方法调用时候帧栈和栈

一个例子
执行过程中的三个快照:
这里写图片描述

Questions:

1 操作指令在栈桢中是如何工作的?

2 帧数据区的作用需要实例化来理解

猜你喜欢

转载自blog.csdn.net/weixin_38719347/article/details/80889505