学习JVM-基础篇-Java虚拟机栈&本地方法栈

Java虚拟机栈

Java虚拟机栈是JVM 为每个线程分配的私有内存区域,用于存储方法调用的上下文信息。每当线程调用一个 Java 方法时,JVM 会创建一个新的栈帧压入栈顶;方法执行完毕后,栈帧被弹出。栈采用先进后出(FILO)原则。

栈帧的结构

栈帧是栈的基本单位,每个方法调用对应一个栈帧。栈帧在方法开始时创建,在方法结束时销毁。包含的组件:

  • 局部变量表

    • 一个固定大小的数组,用于存储方法的参数和局部变量。索引从0开始,非静态方法的索引0存储this 引用,后续索引存储参数和局部变量。

    • 大小在编译时确定,由方法的字节码指令定义。例如,一个方法有3个参数和2个局部变量,局部变量表大小为5。

    • 存储基本数据类型(如int,boolean)和对象引用(reference类型)。基本类型占一个slot(槽位),long和double 占用两个slot。

  • 操作数栈

    • 一个先进后出的栈结构,用于执行字节码指令时的临时数据存储。例如,算术计算会从操作数栈弹出操作数,计算后压入结果。

    • 深度在编译时确定。字节码指令如iload (加载int)将值压入栈,istore 将值存储到局部变量表。

帧数据
  • 动态链接

    • 当前类的字节码指令引用了其他类的属性或者方法时,需要将符号引用(编号)转换成对应的运行时常量池中的内存地址。动态链接就保存了编号到运行时常量池的内存地址的映射关系。
  • 方法返回地址

    • 存储方法退出后应返回的指令地址。对于正常返回,JVM 使用此地址恢复执行;对于异常退出,JVM使用异常表处理。
  • 异常表

    • 异常表存放的是代码中异常的处理信息,包含了异常捕获的生效范围以及异常发生后跳转到的字节码指令位置。
栈内存溢出

Java虚拟机栈如果栈帧过多,占用内存超过内存可以分配的最大大小就会出现内存溢出。内存溢出报 StackOverflowError错误

如果我们不指定栈的大小,JVM将创建一个具有默认大小的栈。大小取决于操作系统和计算机的体系结构。

要修改 Java虚拟机栈的大小,可以使用虚拟机参数 -Xss

语法:-Xss 栈大小

单位:字节(默认,必须是1024倍数)、k或者K(KB)、m或者M(MB)、g或者G(GB)

例如:-Xss1048576 -Xss1024K

OutOfMemoryError:

  • JVM 允许动态扩展栈容量,但无法申请到足够内存(如系统内存耗尽)

  • 创建新线程时无法为栈分配初始内存(例如创建大量线程且 -Xss 设置过大,导致堆外内存不足)

本地方法栈

Java虚拟机栈存储了 Java 方法调用的栈帧,而本地方法栈存储的是native 本地方法的栈帧。

在 Hotspot 虚拟机中,Java虚拟机栈和本地方法栈实际上使用了同一个栈空间。本地方法栈用在内存上生成一个栈帧,临时保存方法的参数同时方便出现异常时也把本地方法的栈信息打印出来。

相关推荐
M78佐菲4 小时前
ARM学习笔记(1)
linux·arm开发·笔记·嵌入式硬件·学习
步行cgn5 小时前
Spring c 命名空间注入详解
java·后端·spring
明月_清风6 小时前
Maven 到底是什么?一篇文章搞懂 Java 项目构建与依赖管理
java·后端·maven
aramae6 小时前
MySQL复合查询(8)
java·c语言·开发语言·后端·算法
Rain的Java大神之路6 小时前
如何快速上传10G文件
java·spring boot·redis·后端·mysql·spring cloud·面试
无敌贵点大王7 小时前
RTThread学习记录11——RT-Thread 设备模型吃透:UART/ADC/PWM/PIN 到底有什么区别?
c语言·stm32·学习·链表
Wang's Blog7 小时前
Java 接入Redis: 通用命令与键管理
java·服务器·redis
Wang's Blog7 小时前
Java 接入Redis: 列表集合与有序集合操作命令
java·服务器·redis
Ivanqhz8 小时前
SVD++算法
java·服务器·网络·深度学习·神经网络
是翎8 小时前
深度长文|2026产品经理AI实践手册
人工智能·深度学习·学习·自然语言处理·数据挖掘