Java中的栈概述及JVM 中的栈结构

 更新时间:2025年10月28日 10:53:38   作者:小满、  
栈是一种受限的线性数据结构,只能在一端(称为 栈顶(Top))进行插入和删除操作,本文给大家介绍Java中的栈概述深入理解JVM中的栈结构,感兴趣的朋友跟随小编一起看看吧

一、什么是栈(Stack)

栈(Stack) 是一种受限的线性数据结构,只能在一端(称为 栈顶(Top))进行插入和删除操作。
它遵循 后进先出(LIFO, Last In First Out) 的原则 —— 后放进去的元素先被取出。

可以把它想象成“叠盘子”的场景:

把盘子一个个叠上去 → 压栈(push)

取盘子时只能从最上面拿 → 弹栈(pop)

这就是栈的直观模型。

二、栈的基本操作

操作含义
push(x)将元素 x 压入栈顶
pop()移除并返回栈顶元素
peek() / top()查看栈顶元素但不删除
isEmpty()判断栈是否为空

三、栈的存储结构

栈可以通过两种方式实现:

顺序栈(Array Stack):
使用数组实现,结构简单、访问高效。

常用于空间大小可预估的情况。

JVM 的操作数栈就是基于数组实现的。

链栈(Linked Stack):
使用链表实现,插入删除灵活,不需要预设大小。

适合栈深不确定的场景(如深度递归)。

四、栈的典型应用场景

1. 函数调用与返回(Call Stack)

当函数 A 调用函数 B 时:

函数 A 的局部变量与返回地址会被压入栈;

JVM 跳转执行函数 B;

当 B 执行完毕后,栈顶记录被弹出,返回 A 的调用点继续执行。

void A() {
    B();
}
void B() {
    System.out.println("Hello Stack");
}

执行流程:

A() 调用 → JVM 为 A 创建栈帧 → 压栈
A 调用 B → JVM 为 B 创建栈帧 → 压栈
B 执行完 → B 的栈帧出栈 → 返回 A
A 执行完 → A 的栈帧出栈

每个方法调用都对应着 一次入栈与出栈操作。
这就是我们常说的“调用栈”。

2. 表达式求值与语法解析

栈是编译器和解释器处理中缀表达式的关键结构。

例如表达式:

(1 + 2) * 3

求值过程(编译器利用栈存储操作符与中间结果):

(1)读取 ( → 压栈(表示新的子表达式)

(2)读取 1 → 压栈(操作数)

(3)读取 + → 压栈(操作符)

(4)读取 2 → 压栈

(5)遇到 ) → 弹出操作符与操作数计算(得到 3),结果压栈

(6)读取 * → 压栈

(7)读取 3 → 压栈

(8)弹出 * 与两个操作数计算(得到 9)

最终结果为 9。

类似逻辑也用于:

括号匹配校验(检查是否“左括号=右括号”)

中缀转后缀(逆波兰表达式)

编译器语法树构建

3. 递归与回溯(Recursion & Backtracking)

递归调用的本质,就是函数不断地入栈与出栈。

例如计算阶乘:

int factorial(int n) {
    if (n == 1) return 1;
    return n * factorial(n - 1);
}

执行 factorial(3) 的过程:

factorial(3) → 入栈
factorial(2) → 入栈
factorial(1) → 入栈
factorial(1) 返回 1 → 出栈
factorial(2) 返回 2 * 1 = 2 → 出栈
factorial(3) 返回 3 * 2 = 6 → 出栈

当最内层函数执行完毕后,系统会逐层弹栈返回结果。
这正是递归函数能“自动返回”的根本原因。

4.其他算法中的应用

DFS(深度优先搜索):利用栈保存待访问的节点

括号匹配:用栈判断表达式是否合法

浏览器前进/后退:前进与回退分别用两个栈保存历史

撤销(Undo)操作:通过栈记录每次修改历史,支持一步步撤销

五、栈在 JVM 中的体现

JVM 是一台 基于栈的虚拟机
这里的“栈”指的是 每个线程独有的 JVM 栈(Java Virtual Machine Stack)。
它记录了方法调用过程与执行状态,是 Java 程序运行的核心结构。

1.JVM 栈的结构与作用

当线程创建时,JVM 会为其分配一个独立的 JVM 栈。
每次方法调用时,都会在这个栈中创建一个 栈帧(Stack Frame)。

每个栈帧包含以下关键部分:

组成部分说明
局部变量表(Local Variables)存储方法参数与局部变量
操作数栈(Operand Stack)临时计算区,用于执行字节码运算
动态链接指向运行时常量池中该方法的引用
方法返回地址方法执行完后返回调用点

当方法被调用时:栈帧入栈
当方法执行完毕时:栈帧出栈

每个线程的调用链条就是 JVM 栈帧的入栈与出栈过程。

2. 操作数栈:JVM 的“计算引擎”

JVM 并不像 CPU 一样通过寄存器运算,而是依靠 操作数栈(Operand Stack) 来完成计算。

例如:

int a = 1;
int b = 2;
int c = a + b;

对应字节码:

0: iconst_1    // 将常量1压入栈
1: istore_1    // 弹出1,存入局部变量表槽1 (a)
2: iconst_2    // 压入常量2
3: istore_2    // 弹出2,存入槽2 (b)
4: iload_1     // 取出a压入操作数栈
5: iload_2     // 取出b压入操作数栈
6: iadd        // 弹出两个数相加,结果压栈
7: istore_3    // 弹出结果,存入槽3 (c)

所有运算都通过“压入栈 → 运算 → 弹出”完成。

这正是 JVM 基于栈结构执行指令的直接体现。

3. JVM 调用栈过程

例如:

public static void main(String[] args) {
    foo();
}
public static void foo() {
    bar();
}
public static void bar() {}

执行过程:

步骤事件栈状态(自下而上)
main() 开始执行[main]
main 调用 foo()[main → foo]
foo 调用 bar()[main → foo → bar]
bar 执行完毕[main → foo]
foo 执行完毕[main]
main 执行完毕[](空栈)

可以把调用栈理解为“任务清单叠叠乐”:
每次调用方法就是“加一张任务卡”,执行完就“拿掉最上面的那张”。

六、栈与 JVM 的关系对照表

内容栈的普通概念JVM 中的体现
存储单位元素栈帧(Stack Frame)
操作方式push / pop方法调用 → 入栈,方法返回 → 出栈
访问原则LIFO(后进先出)方法的调用与返回顺序
主要用途表达式计算、递归、回溯保存局部变量、执行指令、维护调用链
结构组成栈顶、栈底局部变量表 + 操作数栈 + 链接信息

五、总结

        栈(Stack)是一种遵循“后进先出”(LIFO)原则的线性数据结构,只能在一端进行插入和删除操作,常用来保存临时数据和控制程序执行流程。在计算机中,栈的思想贯穿编译、运行与算法设计全过程:在算法中用于递归、回溯、括号匹配、撤销操作等;在编译器中用于表达式求值和语法解析;在 JVM 中,每个线程都有独立的 JVM 栈,用来管理方法调用,通过“栈帧”的入栈与出栈保存局部变量、返回地址和计算过程,操作数栈则承担所有计算任务。可以说,栈不仅是数据结构中的重要基础,更是理解程序执行机制、方法调用过程和虚拟机底层原理的核心。

到此这篇关于Java中的栈概述及JVM 中的栈结构的文章就介绍到这了,更多相关java jvm栈内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于java线程安全问题及原理性分析

    基于java线程安全问题及原理性分析

    下面小编就为大家带来一篇基于java线程安全问题及原理性分析。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • Java实现合并多个升序链表

    Java实现合并多个升序链表

    本文主要介绍了Java实现合并多个升序链表,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Java编程实现基于图的深度优先搜索和广度优先搜索完整代码

    Java编程实现基于图的深度优先搜索和广度优先搜索完整代码

    这篇文章主要介绍了Java编程实现基于图的深度优先搜索和广度优先搜索完整代码,具有一定借鉴价值,需要的朋友可以了解下。
    2017-12-12
  • Java中JFinal框架动态切换数据库的方法

    Java中JFinal框架动态切换数据库的方法

    这篇文章主要介绍了Java中JFinal框架动态切换数据库的方法,本文通过两种方法结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Java中值传递和引用传递的区别

    Java中值传递和引用传递的区别

    这篇文章主要介绍了Java中值传递和引用传递的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • SpringBoot中整合Ehcache实现热点数据缓存的详细过程

    SpringBoot中整合Ehcache实现热点数据缓存的详细过程

    这篇文章主要介绍了SpringBoot中整合Ehcache实现热点数据缓存,SpringBoot 中使用 Ehcache 比较简单,只需要简单配置,说白了还是 Spring Cache 的用法,合理使用缓存机制,可以很好地提高项目的响应速度,需要的朋友可以参考下
    2023-04-04
  • SpringBoot @value注解动态刷新问题小结

    SpringBoot @value注解动态刷新问题小结

    @Value注解 所对应的数据源来自项目的 Environment 中,我们可以将数据库或其他文件中的数据,加载到项目的 Environment 中,然后 @Value注解 就可以动态获取到配置信息了,这篇文章主要介绍了SpringBoot @value注解动态刷新,需要的朋友可以参考下
    2023-09-09
  • SpringBoot整合jasypt加密配置文件敏感信息

    SpringBoot整合jasypt加密配置文件敏感信息

    在项目中我们需要对配置文件的一些敏感信息进行加密处理,比如数据库账户密码,避免直接暴露出来,这种场景常常用于生产环境,我们不想让开发人员知道生产库的密码,有运维人员统一管理,所以本文给大家介绍了SpringBoot整合jasypt加密配置文件敏感信息
    2024-06-06
  • Java中HashMap和Hashtable及HashSet的区别

    Java中HashMap和Hashtable及HashSet的区别

    以下是对Java中HashMap和Hashtable及HashSet的区别进行了详细的分析介绍,需要的朋友可以过来参考下
    2013-09-09
  • Java JVM字节码指令集总结整理与介绍

    Java JVM字节码指令集总结整理与介绍

    本节将会着重介绍一下JVM中的指令集、Java是如何跨平台的、JVM指令集参考手册等内容。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09

最新评论