news 2026/9/3 6:28:42

Java堆栈叫法专坑新人!堆和栈的区别,一个存储对象一个记方法调用,整不明白就别写代码了

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java堆栈叫法专坑新人!堆和栈的区别,一个存储对象一个记方法调用,整不明白就别写代码了

有点明白堆是heap, 栈是stack, 而堆栈实际上是栈。嗯呐, 我是真的特别不喜欢“堆栈”这种称谓, 它很容易致使新人掉进坑里。JVM的规范使得每个Java线程享有自身独立的JVM栈, 这就是Java方法的调用栈。

与此同时, JVM规范为了能够让代码去调用Java代码, 并且还能让Java代码调用方法, 于是规定每个Java线程都有自己独立的方法栈。这俩均是JVM规范所规定的概念范畴内的事物, 并非是讲具体的JVM实现切实要为每个Java线程开辟两个独立的栈。

拿JDK / 的VM来说, 它运用所谓的“mixed stack”, 即于同一个调用栈里放置Java方法的栈帧以及方法的栈帧, 故而每个Java线程实际上仅有一个调用栈, 此调用栈融合了JVM规范的JVM栈与方法栈这两个概念。JVM里叫做“堆”(heap)的部分专门用来存放Java对象的内存区域。所以依据这个定义, Java对象全都处于堆上。需留意, 此“堆”并非数据结构层面的那个堆(Heap (data ), 一种有序的树), 而是动态内存分配意义范畴的堆——用以管理动态生存期的内存区域。JVM的堆被同一个JVM实例里的所有Java线程共同分享。

它通常由某种自动内存管理机制进行管理 , 这种机制通常称作“垃圾回收”( , GC)。JVM规范并不硬性规定JVM实现采用何种GC算法。把堆同栈区分开来, 依据其对应功能, 栈内存肩负起存储局部变量以及方法调用的职责, 不过堆内存充当起存储Java里对象的场所, 各类变量, 像是成员变量, 局部变量, 或者类变量, 它们所指向的对象统统存储于堆内存区域内。以共享性为着眼点, 栈内存具备线程私有的特性, 堆内存则是所有线程都可共有的。当涉及异常错误方面, 一旦栈内存或者堆内存出现不足的状况, 就会抛出异常, 具体而言, 栈空间不足时会出现java.lang., 堆空间不足时会出现java.lang.。就空间大小而言, 栈的空间大小相较于堆的要小很多。深入理解栈, 栈帧由三部分构成, 分别是局部变量区、操作数栈、帧数据区, 局部变量区和操作数栈大小依对应的方法而定, 它们按字长计算, 调用一个方法时, 它从类型信息里获取此方法局部变量区和操作数栈大小, 依据此来分配栈内存, 随后压入Java栈。

局部变量区, 它被组织成以一个字长作为单位, 且从0开始计数的数组, 其中类型为short、byte以及char的值, 如果要存入数组的话, 在存入前提要被转换成int值;并且long和在这部数组中占据连续的两项, 如果说在访问局部变量中的long或的时候, 仅仅只需取出连续两项的第一项的索引值就行啦, 就好像某个long值在局部变量区中等所在的索引是这三项, 第一项是比如说是3, 它的第二项是index对应的4那样, 取值时刻, 指令仅仅只需取索引为3的long值就可以的。像是这样的代码以及图所展示的: ``` int (int i,long l,float f, d, o,byte b) { 0;} int (char c, d,short s, b) { 0;}```!()### 操作数栈, 它跟局部变量区是一样的情况, 操作数栈同样被构建成一个以字长作为单位的数组, 然而和前者存在差异的是, 它并非借助索引来进行访问, 而是依靠入栈以及出栈这种方式来实现访问的, 能够将操作数栈理解成在存储计算的时候, 用于临时数据的一个存储区域。

紧接着, 借助一段简短的程序片段, 再搭配一幅图片, 以此来弄明白操作数栈所具备的作用。``` int a = 100; int b = 98; int c = a+b; ```!()由图能够推断出: 操作数栈实际上就是一个临时的数据存储区域, 它依靠入栈以及出栈的方式来开展操作。### 帧数据区 在局部变量区以及操作数栈之外, java栈帧还需要一些数据去支撑常量池解析、正常方法返回以及异常派发机制。那些数据全都被保存在java栈帧的帧数据区之内。

当JVM执行至需要常量池数据的指令之际, 它都会借助帧数据区中指向常量池的指针去访问它。 除了对常量池解析进行处理之外, 帧里的数据还要处理java方法的正常结束以及异常终止。要是通过正常结束, 那么当前栈帧会从Java栈中弹出, 恢复发起调用的方法的栈。要是方法存在返回值, JVM会将返回值压入到发起调用方法的操作数栈。帧数据区得保存一个针对此方法异常引用表的引用, 这是为了去处理java方法里的异常状况。

当异常被抛出时, JVM会把代码给予catch块中的代码。要是没找到, 方法会马上去终止, 接着JVM会利用帧区数据的信息, 去恢复发起调用的方法的帧。之后在发起调用方法的上下文里, 再次抛出同样的异常。### 栈的整个结构, 栈是由栈帧构成的, 每当线程调用一个java方法之际, JVM会在该线程对应的栈当中压入一个帧, 然而帧是由局部变量区、操作数栈以及帧数据区组成的。那在一个代码块中,栈到底是什么形式呢?下面是《深入JVM》里的一个例子: ```class Main{void (){=(1,88.88);.out.();}(int i, d){i + d;}}```执行进程里的三个快照: !()上面这幅图表明两件事儿: 1、唯有在调用某一个方法之际, 才会为当前的栈分配一个帧, 接着把这个帧压进栈;2、帧当中存放着对应方法的局部数据, 当方法执行完毕后, 对应的帧便从栈当中弹出, 并且将返回结果存储在调用该方法的帧的操作数栈当中。

按照操作系统里进程的内存结构来阐释, 下图描绘的是linux里一个进程的虚拟内存分布情况, 图中0号地址处于最下方, 越往上方内存地址便越大, 以32位地址的操作系统而言, 一个进程所能拥有的虚拟内存地址范围是0到2的32次方, 可划分为两部分, 一部分被用于其他用途, 剩余的则供进程自身使用, 也就是图中的部分, 普通Java程序所使用的正是这部分。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/3 6:27:38

横断面地面线数据反推平距高程并导入Excel的完整方法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/3 6:27:10

STM32直流电机PID调速实战:从硬件架构到参数整定全解析

简介:本资源是一套基于STM32F103C8T6芯片实现直流有刷电机闭环PID调速的完整嵌入式开发工程,面向嵌入式初学者、电机控制实践者及自动化专业学生,解决直流电机精准稳速控制这一典型控制工程问题。压缩包共220个文件,含38个C源码&a…

作者头像 李华
网站建设 2026/9/3 6:24:30

基于微信小程序的高尔夫球场管理系统的设计与实现(程序+文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

作者头像 李华
网站建设 2026/9/3 6:24:19

CBTC信号系统安全:一文讲透车载ATP认证与信号系统访问控制,收藏这篇就够了

地铁车辆段信号车间,凌晨两点的作业窗口。工班长把维护 UKey 插进 ATS 维护工作站,输入口令,屏幕弹出一个账号下拉框——这个账号是五家厂商驻场工程师共用的。旁边那台给车载 VOBC 灌升级包的电脑,U 盘拷进去直接刷,没人校验签名。信号是 SIL4 的安全系统,可管着它的人,认证还…

作者头像 李华