java中堆栈(stack)和堆(heap)【转摘】
地址:http://blog.csdn.net/jerryao/archive/2006/07/04/874101.aspx
一、堆栈(stack)和堆(heap)?
(1)内存分配的策略
按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的.
静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求.
栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的.和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未知的,只有到运行的时候才能够知道,但是规定在运行中进入一个程序模块时,必须知道该程序模块所需的数据区大小才能够为其分配内存.和我们在数据结构所熟知的栈一样,栈式存储分配按照先进后出的原则进行分配。
静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在过程的入口处必须知道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时模块入口处都无法确定存储要求的数据结构的内存分配,比如可变长度串和对象实例.堆由大片的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放.
(2)堆和栈的比较
上面的定义从编译原理的教材中总结而来,除静态存储分配之外,都显得很呆板和难以理解,下面撇开静态存储分配,集中比较堆和栈:
从堆和栈的功能和作用来通俗的比较, 堆主要用来存放对象的,栈主要是用来执行程序的 .而这种不同又主要是由于堆和栈的特点决定的:
在编程中,例如C/C++中,所有的方法调用都是通过栈来进行的,所有的局部变量,形式参数都是从栈中分配内存空间的。实际上也不是什么分配,只是从栈顶向上用就行,就好像工厂中的传送带(conveyor belt)一样,Stack Pointer会自动指引你到放东西的位置,你所要做的只是把东西放下来就行.退出函数的时候,修改栈指针就可以把栈中的内容销毁.这样的模式速度最快, 当然要用来运行程序了.需要注意的是,在分配的时候,比如为一个即将要调用的程序模块分配数据区时,应事先知道这个数据区的大小,也就说是虽然分配是在程序运行时进行的,但是分配的大小多少是确定的,不变的,而这个"大小多少"是在编译时确定的,不是在运行时.
堆是应用程序在运行的时候请求操作系统分配给自己内存,由于从操作系统管理的内存分配,所以在分配和销毁时都要占用时间,因此用堆的效率非常低.但是堆的优点在于,编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间,因此,用堆保存数据时会得到更大的灵活性。事实上,面向对象的多态性,堆内存分配是必不可少的,因为多态变量所需的存储空间只有在运行时创建了对象之后才能确定.在C++中,要求创建一个对象时,只需用 new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存.当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!这也正是导致我们刚才所说的效率低的原因,看来列宁同志说的好,人的优点往往也是人的缺点,人的缺点往往也是人的优点(晕~).
(3)JVM中的堆和栈
JVM是基于堆栈的虚拟机.JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。
我们知道,某个线程正在执行的方法称为此线程的当前方法.我们可能不知道,当前方法使用的帧称为当前帧。当线程激活一个Java方法,JVM就会在线程的 Java堆栈里新压入一个帧。这个帧自然成为了当前帧.在此方法执行期间,这个帧将用来保存参数,局部变量,中间计算过程和其他数据.这个帧在这里和编译原理中的活动纪录的概念是差不多的.
从Java的这种分配机制来看,堆栈又可以这样理解:堆栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特性。
每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程共享.跟C/C++不同,Java中分配堆内存是自动初始化的。Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已
分享到:
相关推荐
cs_basics 回顾cs概念,包括二进制搜索树(addNode,removeNode,findNode,inOrderTraversal,preOrderTraversal,postOrderTraversal的操作),链接列表,堆栈,队列和图构造。 非常感谢以下来源:来源: : Sesh ...
队列、堆栈、双端队列 树结构,树集 堆,优先队列 Guava(谷歌核心 Java 库 链表,ArrayDeque 哈希,哈希表 LRUCache 缓存,LinkedHashMap 其他开源 Java 库 课程大纲 - Java 算法 第 1 周 - 线性结构 第二周 - 树状...
在“设计”小节中探讨了我的设计和替代设计的理由。 设计 为了了解决策,让我们回顾一下要求: Bjorn希望在Windows和MacOS机器上运行该程序-需要交叉可比性 珍妮(Jeanie)需要该计划具有成本效益-可能应该使用免费...
非科班出身程序员刷题 课程辅导计划表(持续更新ing) [TOC] 1 课程目标 ...顺序和链接的存储表示形式:列表,堆栈,队列和表。非线性数据结构:树和图。递归,排序,搜索和算法复杂度。 3 [CSE 278]( 278)
4.8 从原生代码中调用Java 108 4.8.1 异步通信 108 4.8.2 启用Directors 109 4.8.3 启用RTTI 109 4.8.4 重写回调方法 109 4.8.5 更新HelloJni Activity 110 4.9 小结 110 第5章 日志、调试及故障处理 111 ...
您应该花些时间回顾一下我。 已知语言: Java脚本 React Redux HTML CSS Ruby 滑轨 SQL PostgreSQL SQLite的 吉特 Webpack 赫鲁库 MongoDB的 我创建的项目: 气泡 Bubbles是一款2D游戏,您可以在其中控制...
选择自己的技术堆栈-可能使用React,java,mongodb。 使用一些第三方库-发现这些库可能有助于探索思路: Material-ui React网格? React-geo /鸽子地图/ google-map-react / react-mapbox / react-maps React-...
学习使用Java脚本进行全栈开发的基本技术和概念(React / Node.js); 每天进行远程工作的方法。 将向您介绍的技术 Git / Git流。 码头工人 数据库:PostgreSQL。 Javascript堆栈:React和Node.js。 使用JWT进行...
目前,它具有C / C ++,Python和一些Java实现的功能。 它包含许多高级算法,例如贪婪算法,图遍历算法(包括Dijkstra算法和Floyd Warshal算法)以及数据结构(例如队列,堆栈和二进制搜索树)。 贡献很高。 使用此...
数据结构内容:循环和递归数组和矩阵链表队列,堆栈,堆,集合和哈希图,树和二进制搜索,图,深度优先搜索,广度优先搜索和回溯尝试,合并排序和快速排序其他有用的内容:具有多个指针或滑动Windows贪婪算法的动态...
3.4.2. 设计回顾 3.4.3. 配置选项 3.4.4. Resolvers 3.4.4.1. 文件 Resolver 3.4.5. 基本用法 4. Zend_Cache 4.1. 简介 4.2. 缓存原理 4.2.1. Zend_Cache 工厂方法 4.2.2. 标记纪录 4.2.3. 缓存清理 4.3. ...
别被下面那些复杂的表达式吓倒,只要跟着我一步一步来,你会发现正则表达式其实并没有你想像中的那么困难。当然,如果你看完了这篇教程之后,发现自己明白了很多,却又几乎什么都记不得,那也是很正常的——我认为,...