Java虚拟机组成之虚拟机栈

 更新时间:2026年06月22日 10:47:47   作者:sheeta1998  
这段描述概括了Java虚拟机(JVM)中的虚拟机栈(VMStack)的关键组成部分及其功能,包括局部变量表、操作数栈和方法返回地址等,详细解释了栈帧的结构和作用,以及栈内存管理、线程安全性和常见面试问题,感兴趣的朋友一起看看吧

Java虚拟机(JVM)是运行Java字节码的虚拟机,它是Java平台的核心组成部分。JVM主要负责执行Java程序,并提供运行时环境。JVM的实现包括几个关键组件,其中虚拟机关键组件之一是“虚拟机栈”(VM Stack),它是Java内存区域的一部分,用于存储局部变量和部分操作结果。

虚拟机栈的作用

虚拟机栈(VM Stack)主要用于存储局部变量、操作数以及方法调用的返回地址等信息。每个线程在创建时都会分配一个私有的虚拟机栈,它不会发生线程之间的共享。

虚拟机栈的结构

每个栈帧(Stack Frame)对应一个方法,它包含了以下信息:

  • 局部变量表‌:存放编译期可知的各种基本数据类型(byte, short, int, long, float, double, boolean, char, returnAddress)、对象引用(reference type)和returnAddress类型(指向一条字节码指令的地址)。
  • 操作数栈‌:也常被称为表达式栈,用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。
  • 动态链接‌:指向运行时常量池的方法引用,这部分用于支持动态语言的关键功能变化,如重写等。
  • 方法出口‌:存放方法正常退出或者异常退出的定义,这包括程序计数器的恢复等。

虚拟机栈的管理

  • 栈深度‌:每个线程的栈深度可以通过JVM参数(如-Xss)来设置。如果超出这个限制,会抛出StackOverflowError异常。
  • 内存分配‌:每次方法调用时,JVM都会为该方法创建一个新的栈帧并入栈,方法返回时,相应的栈帧被弹出。
  • 异常处理‌:如果线程请求的栈深度超过了虚拟机允许的最大深度,将抛出StackOverflowError。如果虚拟机栈可以动态扩展但无法申请足够内存时,会抛出OutOfMemoryError异常。

一、基础定义

  1. 线程私有:每个线程独占一份虚拟机栈,生命周期和线程同步;
  2. 存储内容:存放方法调用过程,遵循先进后出;
  3. 组成单元:每一次方法调用都会创建一个栈帧(Frame),方法执行完毕栈帧出栈释放;
  4. 活动栈帧:同一线程同一时刻只有顶部栈帧为活动栈帧,对应当前正在执行的方法。

二、栈帧内部存储内容

  1. 局部变量表
    存放方法参数、方法内局部变量(基本类型、对象引用地址)。
  2. 操作数栈
    字节码运算临时缓冲区,执行加减、对象创建、方法传参时临时存放数据。
  3. 动态链接(运行时常量池引用)
    指向方法区常量池符号引用,运行时解析为实际方法地址。
  4. 方法返回地址
    方法执行结束后,回到调用处的字节码行号,正常返回/异常返回都依靠该地址恢复执行。
  5. 附加信息(可选):异常表、附加调试信息。

三、高频面试问题

1. 垃圾回收是否处理栈内存?

GC主要回收堆内存;栈内存不需要GC,方法执行完成栈帧直接出栈,内存自动释放。

2. 栈内存越大越好吗?

不是,默认栈大小一般1024K(-Xss参数调整)。
单栈内存设置越大,机器整体能创建的并发线程数量越少,会降低服务并发承载能力。

3. 方法局部变量是否线程安全?

  • 局部对象不逃出方法作用域:线程安全。每个线程栈帧独有局部变量,无共享竞争;
  • 局部对象通过参数传递/return返回,逃逸到其他线程:线程不安全,多线程并发修改会出现数据错乱。
    示例:
// 安全:sb仅当前栈帧使用,不对外暴露
public void m1(){
    StringBuilder sb = new StringBuilder();
    sb.append("123");
}
// 不安全:sb引用传递给其他线程共享
public void m2(StringBuilder sb){
    sb.append("456");
}
// 不安全:将局部对象返回,外部多线程共用
public StringBuilder m3(){
    StringBuilder sb = new StringBuilder();
    return sb;
}

4. 栈内存溢出 StackOverflowError 两种场景

  1. 递归调用无终止条件,创建大量栈帧,栈深度超限;
public void m4(){
    m4(); // 无限递归,抛出StackOverflowError
}
  1. 单个栈帧局部变量、操作数栈占用过大,单帧超过栈容量。

四、堆与虚拟机栈核心区别

  1. 归属:栈是线程私有;堆是全线程共享。
  2. 存储:栈存局部变量、方法调用栈帧;堆存所有对象、数组实例。
  3. 回收:堆依靠GC回收;栈方法结束自动出栈释放,无GC。
  4. 溢出异常:
  • 栈不足:java.lang.StackOverflowError
  • 堆不足:java.lang.OutOfMemoryError: Java heap space

五、面试简答

问:虚拟机栈里的栈帧存放什么?

答:
每个方法调用对应一个栈帧,栈帧包含五部分:局部变量表、操作数栈、动态链接、方法返回地址、附加信息。
局部变量表存方法参数与局部变量;操作数栈用于字节码运算临时存数据;动态链接指向常量池解析方法;返回地址记录调用处位置,方法结束后恢复上层代码执行。

到此这篇关于Java虚拟机组成之虚拟机栈的文章就介绍到这了,更多相关java虚拟机栈内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot 自动装配的几种用法示例小结

    Spring Boot 自动装配的几种用法示例小结

    文章介绍了SpringBoot自动装配的多种用法,包括基础的@Bean注册、策略模式通过applicationContext获取指定Service实现类,以及高级的获取接口所有实现类集合和Map映射,感兴趣的朋友跟随小编一起看看吧
    2025-07-07
  • 关于快速测试API接口的一个新技能

    关于快速测试API接口的一个新技能

    这篇文章主要给大家介绍了关于快速测试API接口的一个新技能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-06-06
  • idea项目保存位置设置

    idea项目保存位置设置

    以上内容主要描述了在idea中设置项目保存位置的方法,无论是中文模式还是还是还是还是英文模式,其实现操作路径为:设置-外观与行为-系统设置Defaultdirectory,这仅是个人经验分享,希望能够为大家提供参考
    2026-04-04
  • Springboot项目快速实现Aop功能

    Springboot项目快速实现Aop功能

    这篇文章主要介绍了Springboot项目如何快速实现Aop功能,对此方面感兴趣的小伙伴可以详细参考阅读本文,本文有一定的参考价值
    2023-03-03
  • Java 中不全部使用 Static 方法的理由

    Java 中不全部使用 Static 方法的理由

    这篇文章主要介绍了Java 中不全部使用 Static 方法的理由,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • 基于bufferedreader的read()与readline()读取出错原因及解决

    基于bufferedreader的read()与readline()读取出错原因及解决

    这篇文章主要介绍了bufferedreader的read()与readline()读取出错原因及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 详解SpringBoot封装使用JDBC

    详解SpringBoot封装使用JDBC

    这篇文章主要介绍了SpringBoot封装JDBC使用教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • 关于BindingResult的使用总结及注意事项

    关于BindingResult的使用总结及注意事项

    这篇文章主要介绍了关于BindingResult的使用总结及注意事项,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Spring中的AOP面向切面编程详解

    Spring中的AOP面向切面编程详解

    这篇文章主要介绍了Spring中的AOP面向切面编程详解,AOP 即面向切面编程,和 OOP面向对象编程类似,也是一种编程思想,AOP采取横向抽取机制(动态代理),取代了传统纵向继承机制的重复性代码,其应用主要体现在事务处理、日志管理、权限控制等方面,需要的朋友可以参考下
    2024-01-01
  • java调用Oracle存储过程的方法实例

    java调用Oracle存储过程的方法实例

    这篇文章介绍了java调用Oracle存储过程的方法实例,有需要的朋友可以参考一下
    2013-09-09

最新评论