heap 和stack 有什么区别

简介: heap 和stack 有什么区别

heap 和stack 有什么区别?
(1)申请方式

stack:由系统自动分配。例如,声明在函数中一个局部变量 int b; 系统自动在栈中为 b 开辟空间

heap:需要程序员自己申请,并指明大小,在 c 中 malloc 函数,对于Java 需要手动 new Object()的形式开辟

(2)申请后系统的响应

stack:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

heap:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

(3)申请大小的限制

stack:栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS 下,栈的大小是 2M(默认值也取决于虚拟内存的大小),如果申请的空间超过栈的剩余空间时,将提示 overflow。因此,能从栈获得的空间较小。

heap:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的, 自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见, 堆获得的空间比较灵活,也比较大。

(4)申请效率的比较

stack:由系统自动分配,速度较快。但程序员是无法控制的。

heap:由 new 分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。

(5)heap和stack中的存储内容

stack:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址, 然后是函数的各个参数,在大多数的 C 编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。

当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。

heap:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。

什么情况下会发生栈内存溢出?
1、栈是线程私有的,栈的生命周期和线程一样,每个方法在执行的时候就会创建一个栈帧,它包含局部变量表、操作数栈、动态链接、方法出口等信息,局部变量表又包括基本数据类型和对象的引用; 2、当线程请求的栈深度超过了虚拟机允许的最大深度时,会抛出StackOverFlowError异常,方法递归调用肯可能会出现该问题; 3、调整参数-xss去调整jvm栈的大小

谈谈对 OOM 的认识?如何排查 OOM 的问题?
除了程序计数器,其他内存区域都有 OOM 的风险。

栈一般经常会发生 StackOverflowError,比如 32 位的 windows 系统单进程限制 2G 内存,无限创建线程就会发生栈的 OOM
Java 8 常量池移到堆中,溢出会出 java.lang.OutOfMemoryError: Java heap space,设置最大元空间大小参数无效;
堆内存溢出,报错同上,这种比较好理解,GC 之后无法在堆中申请内存创建对象就会报错;
方法区 OOM,经常会遇到的是动态生成大量的类、jsp 等;
直接内存 OOM,涉及到 -XX:MaxDirectMemorySize 参数和 Unsafe 对象对内存的申请。
排查 OOM 的方法:

增加两个参数 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof,当 OOM 发生时自动 dump 堆内存信息到指定目录;
同时 jstat 查看监控 JVM 的内存和 GC 情况,先观察问题大概出在什么区域;
使用 MAT 工具载入到 dump 文件,分析大对象的占用情况,比如 HashMap 做缓存未清理,时间长了就会内存溢出,可以把改为弱引用 。
谈谈 JVM 中的常量池?
JVM常量池主要分为Class文件常量池、运行时常量池,全局字符串常量池,以及基本类型包装类对象常量池。

Class文件常量池。class文件是一组以字节为单位的二进制数据流,在java代码的编译期间,我们编写的java文件就被编译为.class文件格式的二进制数据存放在磁盘中,其中就包括class文件常量池。
运行时常量池:运行时常量池相对于class常量池一大特征就是具有动态性,java规范并不要求常量只能在运行时才产生,也就是说运行时常量池的内容并不全部来自class常量池,在运行时可以通过代码生成常量并将其放入运行时常量池中,这种特性被用的最多的就是String.intern()。
全局字符串常量池:字符串常量池是JVM所维护的一个字符串实例的引用表,在HotSpot VM中,它是一个叫做StringTable的全局表。在字符串常量池中维护的是字符串实例的引用,底层C++实现就是一个Hashtable。这些被维护的引用所指的字符串实例,被称作”被驻留的字符串”或”interned string”或通常所说的”进入了字符串常量池的字符串”。 
基本类型包装类对象常量池:java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外上面这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,也即对象不负责创建和管理大于127的这些类的对象。

相关文章
【Java基础面试十三】、面向对象的三大特征是什么?
这篇文章介绍了面向对象程序设计的三大基本特征:封装、继承和多态,其中封装隐藏对象实现细节,继承实现软件复用,多态允许子类对象表现出不同的行为特征。
【Java基础面试十三】、面向对象的三大特征是什么?
|
机器学习/深度学习 计算机视觉
RT-DETR改进策略【Conv和Transformer】| GRSL-2024最新模块 卷积和自注意力融合模块 CAFM 减少图像中的噪声干扰
RT-DETR改进策略【Conv和Transformer】| GRSL-2024最新模块 卷积和自注意力融合模块 CAFM 减少图像中的噪声干扰
555 19
RT-DETR改进策略【Conv和Transformer】| GRSL-2024最新模块 卷积和自注意力融合模块 CAFM 减少图像中的噪声干扰
|
算法 数据安全/隐私保护
基于GARCH-Copula-CVaR模型的金融系统性风险溢出效应matlab模拟仿真
本程序基于GARCH-Copula-CVaR模型,使用MATLAB2022A仿真金融系统性风险溢出效应。核心功能包括计算违约点、资产价值波动率、信用溢价及其直方图等指标。GARCH模型用于描述资产收益波动性,Copula捕捉依赖结构,CVaR度量极端风险。完整代码无水印输出。 具体步骤:首先通过GARCH模型估计单个资产的波动性,再利用Copula方法构建多资产联合分布,最后应用CVaR评估系统性风险。程序展示了详细的运行结果和图表分析,适用于金融市场风险量化研究。
|
数据可视化 算法 Python
基于OpenFOAM和Python的流场动态模态分解:从数据提取到POD-DMD分析
本文介绍了如何利用Python脚本结合动态模态分解(DMD)技术,分析从OpenFOAM模拟中提取的二维切片数据,以深入理解流体动力学现象。通过PyVista库处理VTK格式的模拟数据,进行POD和DMD分析,揭示流场中的主要能量结构及动态特征。此方法为研究复杂流动系统提供了有力工具。
1239 2
基于OpenFOAM和Python的流场动态模态分解:从数据提取到POD-DMD分析
|
存储 人工智能 自然语言处理
高效档案管理案例介绍:文档内容批量结构化解决方案解析
档案文件内容丰富多样,传统人工管理耗时低效。思通数科AI平台通过自动布局分析、段落与标题检测、表格结构识别、嵌套内容还原及元数据生成等功能,实现档案的高精度分块处理和结构化存储,大幅提升管理和检索效率。某历史档案馆通过该平台完成了500万页档案的数字化,信息检索效率提升60%。
601 5
|
Kubernetes 网络安全 网络架构
Docker不同宿主机网络打通
【8月更文挑战第20天】在不同宿主机上打通Docker网络可通过多种方法:1) 使用Docker原生的Overlay或Macvlan网络驱动实现跨主机通信,如Overlay网络利用VXLAN技术连接多台宿主机,Macvlan则让容器直接接入物理网络;2) 利用第三方工具如Weave Net或Flannel构建虚拟网络,Weave Net简化网络配置,Flannel则适用于Kubernetes环境并通过UDP封装数据包实现通信。实施前需确保宿主机间网络畅通且防火墙设置适当。
862 2
|
机器学习/深度学习 人工智能 自然语言处理
什么是深度学习模型?如何部署它?
【8月更文挑战第23天】
1269 0
|
SQL 资源调度 Kubernetes
【收藏+下载】Flink 年度学习资料大礼包!
大数据实时计算及 Apache Flink 年度Flink 年度学习资料大礼包,300+页实战应用精华总结!
【收藏+下载】Flink 年度学习资料大礼包!
|
存储 NoSQL Java
HBase是一个开源的、分布式的、面向列的NoSQL数据库系统
HBase是一个开源的、分布式的、面向列的NoSQL数据库系统
504 0