JVM 虚拟机栈 栈帧

每个线程都有自己的虚拟机栈,栈中存放栈帧(Stack Frame)在这个线程上正在执行的每个方法都对应一个栈帧

栈帧是一个内存区块,是一个数据集,维系着方法执行过程中的各种数据信息。

虚拟机栈只涉及压栈和出栈,只可能栈溢出,不存在垃圾回收

栈溢出:栈不存在GC,但存在OOM StackOverflowError:

1 当函数内部的局部数组过大时,有可能导致堆栈溢出。

2 递归调用层次太多。递归函数在运行时会执行压栈操作,当压栈次数太多时,也会导致堆栈溢出。

设置栈内存的大小-Xss1m等价-XX:ThreadStackSize=1024k。默认1m。

太大会导致内存消耗过大,在一定栈空间下,线程数变小,影响性能。

太小会导致栈溢出。栈大小决定了函数调用的最大可达深度。

方法中定义的局部变量是否线程安全? 如果局部变量在内部产生并在内部消亡的,那就是线程安全的。

  栈帧内容:

1 局部变量表(Local Variables)

2 操作数栈(Operand Stack)

3动态链接(Dynamic Linking)

(或指向运行时常量池的方法引用)

4 方法返回地址(Return Address)

(或方法正常退出或者异常退出的定义)

5 一些附加信息,如对程序调试提供支持的信息。

1 局部变量表 变量槽★

局部变量表

1 ~是一个数字数组,存储方法参数和定义在方法体内的局部变量

2 ~的容量大小在编译期确定,方法运行期间不会改变,Code中的maximum local variables值。

3一个方法参数和局部变量越多,局部变量表越大,栈帧也就越大,进而方法调用就会占用更多的栈空间,嵌套调用次数就会减少。

4 ~的变量只在当前方法调用中有效。调用结束后,随着方法栈帧的销毁,局部变量表也会随之销毁。

5 ~中的变量是重要的垃圾回收根节点GC roots,只要被局部变量表中直接或间接引用的对象都不会被回收。

6 ~建立在线程的栈上,是线程的私有数据,不存在线程安全问题

Slot变量槽:是局部变量表最基本的存储单元。一个slot 32位。

longdouble(64)占两个slot,其他(32位)占一个slot(包括returnAddress)。

对象引用this放在index=0的slot处,其余的参数按照参数表顺序排列。根据索引/序号/index访问。

当一个实例方法被调用的时候,方法参数和局部变量将会按照顺序被复制到局部变量表中的每一个Slot上。

变量槽可以重复利用,节省资源:如果一个局部变量过了其作用域后,新的局部变量可能会复用其槽位。

2 操作数栈★

操作数栈/表达式栈:

1 用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间

2 ~最大深度在编译期就确定了,Code中max_stack值。一个栈深度32位,同上

3 方法刚开始执行,栈帧的操作数栈是空的。

4 方法执行过程中,根据字节码指令,通过标准的入栈push 出栈pop操作,完成数据访问。

5 如果被调用的方法带有返回值的话,其返回值将会被压入当前栈帧的操作数栈中,并更新PC寄存器中下一条需要执行的字节码指令。

栈顶缓存技术(Top-of-Stack Cashing, ToS):由于操作数是存储在内存中的,频繁地执行内存读/写操作必然会影响执行速度。为了解决这个问题,HotSpot JVM的设计者们提出了栈顶缓存技术,将栈顶元素全部缓存在物理CPU的寄存器中,以此降低对内存的读/写次数,提升执行引擎的执行效率。

3 动态链接

动态链接:每一个栈帧内部都包含一个指向运行时常量池中该栈帧所属方法的引用。目的是为了支持当前方法的代码能够实现动态链接(Dynamic Linking)。如invokedynamic指令。

在Java源文件被编译到字节码文件中时,所有的变量和方法引用都作为符号引用(Symbolic Reference)保存在class文件的常量池里。比如:描述一个方法调用了另外的其他方法时,就是通过常量池中指向方法的符号引用来表示的,那么动态链接的作用就是为了将这些符号引用转换为调用方法的直接引用

常量池:提供一些符号和常量,便于指令的识别。

关于静态链接、动态链接、早期绑定、晚期绑定、虚方法等见尚硅谷笔记。

4 方法返回地址

存放调用该方法的pc寄存器的值。

一个方法结束后,都会返回到该方法被调用的位置。

正常退出的,调用者的pc计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址

异常退出的,不会给他的上层调用者返回任何值,返回地址通过异常表确定,栈帧中一般不会保存这部分信息。

本质上,方法的退出就是当前栈帧出栈的过程。此时,需要恢复上层方法的局部变量表、操作数栈、将返回值压入调用者栈帧的操作数栈、设置PC寄存器值等,让调用者方法继续执行下去。

  • 34
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值