当前位置: 首页 > news >正文

二、JVM 入门——(三)栈

栈的定义

栈也是一块区域,用来存放数据的。栈也叫栈内存,主管Java程序的运行。

栈是私有的,是在线程创建时创建,所以它的生命期是跟随线程的生命期,线程结束栈内存也就释放。

因此对于栈来说不存在垃圾回收问题,只要线程一结束该栈就Over,生命周期和线程一致。

这里把方法放进栈里,说的就是方法在栈帧里面。入栈出栈说的都是栈帧。

栈的特点

  • 栈空间也是不需要连续分配,只要在逻辑上相连即可。
  • 栈遵循最基本的栈的数据结构特征:先进后出。
  • 栈空间支付动态调整大小。-xms
  • 栈空间不会出现垃圾回收。(gc作用域不在该区域)
  • 栈的 5 栈的创建时机:在线程创建的时候,随之创建的。
  • 栈属于线程私有区域。
  • 对栈的操作,只有入栈出栈(压栈帧弹栈帧)

存储什么

栈中未来不是直接存放调用的方法,而是存储栈帧。栈帧是栈中最小单元。

8种基本类型的变量+对象的引用变量+returnAddress都是在函数的栈内存中分配。

栈帧中存储:前三个比较重要

  • 存储8种基本数据类型。
  • 存储对象的引用: user未来存储在栈帧中。
User user = new User();
  • 存输方法的返回地址(returnAddress)。
    • 任意一个万法都要存方法出去后的下一条指令地址,哪怕该方法是 void 类型也得存,因为任意的方法在底层字节码都会插入一条字节码指令return
public void a() {...b();...
}public void b() {......
}
  • 存储局部变量表(Local Variable)
  • 操作数栈。(Operate stack)
  • 动态链接(抽象)(Dynamic link)

如图,查看字节码指令多了return

举例

当一个方法A被调用时就产生了一个栈帧 F1,并被压入到栈中,

A方法又调用了 B方法,于是产生栈帧 F2 也被压入栈,

B方法又调用了 C方法,于是产生栈帧 F3 也被压入栈,

……

执行完毕后,先弹出F3栈帧,再弹出F2栈帧,再弹出F1栈帧……

遵循“先进后出”或者“后进先出”原则。

图示在一个栈中有两个栈帧:

栈帧 2是最先被调用的方法,先入栈,

然后方法 2 又调用了方法1,栈帧 1处于栈顶的位置,

栈帧 2 处于栈底,执行完毕后,依次弹出栈帧 1和栈帧 2,

线程结束,栈释放。

每执行一个方法都会产生一个栈帧,保存到栈(后进先出)的顶部,顶部栈就是当前的方法,该方法执行完毕后会自动将此栈帧出栈。

常见问题栈溢出:Exception in thread "main" java.lang.StackOverflowError

通常出现在递归调用时。

JVM对Java栈的操作只有两个,就是对栈帧的压栈和出栈,遵循“先进后出”或者“后进先出”原则。

一个线程中只能由一个正在执行的方法(当前方法),因此对应只会有一个活动的当前栈帧。

当一个方法1(main方法)被调用时就产生了一个栈帧1 并被压入到栈中,栈帧1位于栈底位置

方法1又调用了方法2,于是产生栈帧2 也被压入栈,

方法2又调用了方法3,于是产生栈帧3 也被压入栈,

…… 执行完毕后,先弹出栈帧4,再弹出栈帧3,再弹出栈帧2,再弹出栈帧1,线程结束,栈释放。

深入理解

通过在终端中输入这样的指令,可以去查看下面要讲的内容;或者idea中的jclasslib插件

javap -verbose 类名.class
局部变量表(Local Variables)

也叫本地变量表。 作用:存储方法参数和方法体内的局部变量:8种基本类型变量、对象引用(reference)。 可以用如下方式查看字节码中一个方法内定义的的局部变量,当程序运行时,这些局部变量会被加载到 局部变量表中。

实例方法第一个存的是this,方便去调用方法;而类方法直接可以利用类调用,所以就不需要存储。

局部变量表槽位,一个小方格是一个槽位。

long、double 这种类型是占了两个小方格

实例方法和形参也都会提前放好

  • 报错时,为什么能知道哪里错了?行号表;告诉说是哪一行报错了

操作数栈

作用: 也是一个栈在方法执行过程中根据字节码指令记录当前操作的数据,将它们入栈或出栈。用于保存计算过程的中间结果,同时作为计算过程中变量的临时存储空间。

  • 每一步指令都会严格的入栈出栈,想要深究可以去找pdf步骤。

动态连接

作用:通过符号引用动态确定某些对象。

比如可以知道当前帧执行的是哪个方法对象。程序在运行期间,通过运行时常量池中方法的符号引用,找到方法对象。

执行一个方法的流程:(待定了,先看上面解释即可)

找方法,先得找其类 A,而类在运行时常量池里,包括各种方法,各种属性(这里可能是哪个类在运行,其属性就在里面去找)。

拿到 A 在常量池中的符号 #1, 拿到了符号就可以去常量池拿到了类 A,编译就不会报错。

这是静态链接,只在编译的时候去找。

注意

操作数栈的深度和局部变量表的大小,是在编译阶段确定的。

栈空间溢出

Error Exception 平级,都是继承了 Throwable 类。

IDEA 中可以修改栈的大小,默认是 1MB。

这里是一直递归调用,使得一直使用方法redo导致栈空间爆炸。

// JVM设置  -Xss128k(默认1M)
public class StatckOverflowTest1 {private static int count = 0;public static  void  redo(){count++;redo();}public static void main(String[] args) {try {redo();} catch (Throwable e) {e.printStackTrace();System.out.println("counter====="+count);}}
}java.lang.StackOverflowError
at com.atguigu.jvm.StatckOverflowTest1.redo(StatckOverflowTest1.java:13)
at com.atguigu.jvm.StatckOverflowTest1.redo(StatckOverflowTest1.java:13)
at com.atguigu.jvm.StatckOverflowTest1.redo(StatckOverflowTest1.java:13)
at com.atguigu.jvm.StatckOverflowTest1.redo(StatckOverflowTest1.java:13)
at com.atguigu.jvm.StatckOverflowTest1.redo(StatckOverflowTest1.java:13)
at com.atguigu.jvm.StatckOverflowTest1.redo(StatckOverflowTest1.java:13)
at com.atguigu.jvm.StatckOverflowTest1.redo(StatckOverflowTest1.java:13)
at com.atguigu.jvm.StatckOverflowTest1.redo(StatckOverflowTest1.java:13)
counter=====10213

查看文档链接

http://www.xdnf.cn/news/1370305.html

相关文章:

  • 两数之和,leetCode热题100,C++实现
  • 链改2.0六方会谈协同创新—可信资产IPO与数链金融RWA双轮驱动
  • 第17章|PowerShell 安全警报——高分学习笔记(运维实战向)
  • 使用Kiro智能开发PYTHON应用程序
  • onnx入门教程(五)——实现 PyTorch-ONNX 精度对齐工具
  • Ubuntu操作系统下MySQL、MongoDB、Redis
  • 基于 LQG 控制的轨迹跟踪 —— 从原理到实践
  • 优雅草黑曼巴知识付费项目交付顺带:深入剖析 WebApp 的封装原理与实践-卓伊凡
  • MD5校验算法
  • FreeRTOS 同步互斥与任务协作 学习笔记
  • vscode或者cursor配置使用Prettier - Code formatter来格式化微信小程序wxss/wxs/wxml文件
  • CentOS 7 升级 OpenSSL 3.5.1 的详细教程
  • HarmonyOS image组件深度解析:多场景应用与性能优化指南(2.4详细解析,完整见uniapp官网)
  • Android 属性 property 系统
  • 微服务的编程测评系统16-用户答题
  • 什么是索引下推?
  • ADB 安装教程:如何在 Windows、 Linux 上安装 Android Debug Bridge
  • 基于CSO与BP神经网络分类模型的特征选择方法研究(Python实现)
  • 2025第五届人工智能、自动化与高性能计算国际会议 (AIAHPC 2025)
  • Android Glide生命周期管理:实现原理与最佳实践
  • swift 开发抠图工具实现思路,与代码详解
  • 技术分享︱国产化突破:开源MDO工具链在新一代神威超算上的安装与调试
  • 使用QML的Rectangle组件的边框属性
  • HMM简单拓展-HSMM与高阶HMM
  • C/C++ 数据结构 —— 树(2)
  • nginx-负载均衡
  • C++工程实战入门笔记4-函数(一)
  • WeakAuras Lua Script ICC (BarneyICC) Simplified Chinese [Mini]
  • 深入了解linux系统—— 线程互斥
  • ArcGIS学习-11 实战-商场选址