《JVM第5课》虚拟机栈

无痛快速学习入门JVM,欢迎订阅本免费专栏

Java虚拟机栈(Java Virtual Machine Stack,简称JVM栈,又称Java方法栈)是 JVM 运行时数据区的一部分,主要用于支持Java方法的执行。每当一个新线程被创建时,JVM就会为这个线程分配一个私有的方法栈,线程执行过程中每个方法调用都会创建一个新的栈帧(Stack Frame),而这些栈帧会被组织成后进先出的栈结构。

1 栈知识点

  1. 线程私有

    • 每个线程都有自己的虚拟机栈,与其他线程的栈完全隔离。
    • 线程私有的特性确保了多线程环境下的数据安全和并发执行的效率。
  2. 生命周期与线程相同

    • 虚拟机栈的生命周期与线程的生命周期相同。当线程创建时,虚拟机栈也随之创建;当线程结束时,虚拟机栈也随之销毁。所以虚拟机栈不需要进行垃圾回收
  3. 栈深度

    • 如果方法调用层次过深或者循环调用导致栈帧数量过多,可能会发生栈溢出错误StackOverflowError。但如果线程太多,线程创建时没有足够的内存去创建虚拟机栈,则会抛出OutOfMemoryError错误。
    • 虚拟机栈的深度是可以配置的,通常通过JVM启动参数 -Xss 来设置每个线程的栈大小。合理配置栈深度可以避免栈溢出和内存不足的问题。
  4. 栈帧(Stack Frame)

    • 每个方法调用都会创建一个新的栈帧,并将其压入当前线程的虚拟机栈顶。
    • 当方法执行完毕后,对应的栈帧会被弹出并丢弃。
    • 栈帧是方法执行的基本单位,包含局部变量表、操作数栈、动态链接、方法出口信息等。

2 栈帧

每个栈帧包含了以下部分:

  1. 局部变量表:用于存放方法参数和方法内部定义的局部变量。局部变量表以变量槽(Variable Slot)的形式存在,每个槽可以存放一个基本数据类型、返回地址或者对象引用。对于64位的数据类型(如long和double),需要占用两个连续的槽位。
  2. 操作数栈:顾名思义,就是用来暂存要操作的数据和操作结果的地方。当执行字节码指令时,会从局部变量表或常量池中加载数据到操作数栈,然后根据指令完成相应的计算或操作,最后将结果存回操作数栈或局部变量表。
  3. 动态链接:包括对常量池的引用和对上层方法栈帧的引用,用于支持方法调用过程中的动态链接。
  4. 方法出口信息:包含正常完成出口和异常完成出口的信息,用于处理方法执行完毕后的返回值传递和异常抛出。

当一个方法被调用时,JVM会执行如下步骤:

  1. 创建栈帧:为被调用的方法创建一个新的栈帧,并将其压入当前线程的方法栈顶。
  2. 初始化栈帧:将方法参数传递到新的栈帧的局部变量表中,同时清空操作数栈。
  3. 执行字节码指令:根据方法体中的字节码指令,进行相应的计算和逻辑处理。
  4. 清理栈帧:当方法执行完毕后(无论是正常结束还是异常终止),将结果(如果有)返回给上一层方法,然后从方法栈中弹出当前栈帧。
相关推荐
憨憨崽&23 分钟前
C语言、Java、Python 的选择与未来发展以及学习路线
java·c语言·python
在坚持一下我可没意见1 小时前
Java 网络编程:TCP 与 UDP 的「通信江湖」(基于UDP回显服务器)
java·服务器·开发语言·tcp/ip·udp·java-ee
少爷晚安。1 小时前
Java零基础学习完整笔记,基于Intellij IDEA开发工具,笔记持续更新中
java·笔记·学习
悟能不能悟1 小时前
在service方法中已经catch异常,Transactional失效怎么办
java·数据库·sql
西红柿维生素1 小时前
23种设计模式-框架中的使用
java·开发语言·设计模式
日月星辰Ace1 小时前
JDK 工具学习系列(一):javac、java 命令与 main 方法详解
java
lkbhua莱克瓦242 小时前
Java基础——常用API2
java·笔记·github·学习方法
摇滚侠2 小时前
Spring Boot3零基础教程,Lambda 表达式与函数式接口,笔记95
java·spring boot·笔记
好学且牛逼的马2 小时前
【JavaWeb|day19 Web后端进阶 SpringAOP、SpringBoot原理、自定义Starter、Maven高级】
java·spring boot·rpc
码界奇点2 小时前
Java 开发日记MySQL 与 Redis 双写一致性策略挑战与实战解析
java·redis·sql·mysql·java-ee