栈是后进先出的线性表结构,存取速度比堆快。创建对象的时候new一个对象,引用存在栈上具体的内容存在堆上。
栈与堆都是Java用来在RAM中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。
Java的堆是一个运行时数据区,类的对象从中分配空间。这些对象通过new指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,
堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,
由于要在运行时动态分配内存,存取速度较慢。
栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。
但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。
栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:
int a = 3;
int b = 3;
编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,
因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。
这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。
要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。
String是一个特殊的包装类数据。可以用:
String str = new String("abc");
String str = "abc";
两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。
而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。
比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子说明上面的理论。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
可以看出str1和str2是指向同一个对象的。
String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false
用new的方式是生成不同的对象。每一次生成一个。
因此用第一种方式创建多个”abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。
另一方面, 要注意: 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,创建了String类的对象str。担心陷阱!对象可能并没有被创建!而可能只是指向一个先前已经创建的对象。只有通过new()方法才能保证每次都创建一个新的对象。
由于String类的immutable性质,当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。
2.2申请后系统的响应      
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。  
堆: 首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲 结点链表中删除,
并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。
另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。     
2.3申请大小的限制      
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M
(也可能是1M,它是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。      
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。
堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。        
2.4申请效率的比较:      
栈由系统自动分配,速度较快。但程序员是无法控制的。      
堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活。  
2.5堆和栈中的存储内容  
栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,
参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,
也就是主函数中的下一条指令,程序由该点继续运行。      
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。     
2.6存取效率的比较        char s1[] = "aaaaaaaaaaaaaaa";        char *s2 = "bbbbbbbbbbbbbbbbb";        aaaaaaaaaaa是在运行时刻赋值的;   
而bbbbbbbbbbb是在编译时就确定的;        但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。   
比如: void main(){char a = 1;char c[] = "1234567890";char *p ="1234567890";a = c[1];a = p[1];return;}对应的汇编代码 10: a = c[1];00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]0040106A 88 4D FC mov byte ptr [ebp-4],cl11: a = p[1];0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]00401070 8A 42 01 mov al,byte ptr [edx+1]00401073 88 45 FC mov byte ptr [ebp-4],al第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。        2.7小结:        堆和栈的区别可以用如下的比喻来看出:        使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。        使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

AJPFX总结heap和stack有什么区别?的更多相关文章

  1. heap和stack有什么区别

    1.heap是堆,stack是栈. 2.stack的空间由操作系统自动分配和释放,heap的空间是手动申请和释放的,heap常用new关键字来分配. 3.stack空间有限,heap的空间是很大的自由 ...

  2. 【Java面试题】47 heap和stack有什么区别

    java的内存分为两类,一类是栈内存,一类是堆内存.栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个 ...

  3. 操作系统中 heap 和 stack 的区别

    操作系统中 heap 和 stack 的区别heap 和 stack是什么堆栈是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.==在单片机 ...

  4. sf04_操作系统中 heap 和 stack 的区别

    概述 本文分三部分,描述有所重叠,但可以让你对栈与堆有一个比较清晰.全面的认识 heap 和 stack是什么 堆栈是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top) ...

  5. (转)Java里的堆(heap)栈(stack)和方法区(method)(精华帖,多读读)

    [color=red][/color]<一> 基础数据类型直接在栈空间分配, 方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收.   引用数据类型,需要用new来创建,既在栈 ...

  6. Java里的堆(heap)栈(stack)和方法区(method)

    基础数据类型直接在栈空间分配, 方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收.   引用数据类型,需要用new来创建,既在栈空间分配一个地址空间,又在堆空间分配对象的类变量 . 方法 ...

  7. windows环境下的heap spray+stack pivot gadget 实现绕过dep

    ASLR+DEP是windows平台下最为常见的两种保护手段.这两种手段使得最基础的jmp esp等手法不再适用,而单纯的堆喷也会因为堆内存不可执行而失效.那么这里就来介绍一下heap spray+s ...

  8. Java中的heap和stack

    heap和stack Java的内存分为两类,一类是栈内存,一类是堆内存. 栈内存:是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配 ...

  9. 转:堆(heap)和栈(stack)有什么区别??

    简单的可以理解为: heap:是由malloc之类函数分配的空间所在地.地址是由低向高增长的. stack:是自动分配变量,以及函数调用的时候所使用的一些空间.地址是由高向低减少的. 预备知识—程序的 ...

随机推荐

  1. em和i , b和Strong 的区别

    这两对标签最大区别就是一个给搜索引擎看的,一个是给用户看的. b标签和strong标签给我们的主观感受都是加粗,但对搜索引擎来说b标签和普通的文字并没有什么区别,而strong标签却是起强调作用的. ...

  2. JVM内存分配策略、各个代区、FullGC/MinorGC

    主要讨论默认的Serial/Serial Old内存分配: 一.几种分配方案 1.  对象优先在Eden分配: 一般情况下,对象会在新生代的Eden区分配,Eden区没有足够空间时,虚拟机会 发起一次 ...

  3. NEU 1681: The Singles

    题目描述 The Signals’ Day has passed for a few days. Numerous sales promotion campaigns on the shopping ...

  4. 总结 <stdlib.h>头文件 在算法中可能会用到的一些函数

    头文件<stdlib.>具有一定的总结性. 它定义了类型.宏和各种函数,这些函数用于:内存管理.排序和查找.整形运算.字符串到数字的转换.伪随机数序列.与环境的接口.把多字节字符串和字符转 ...

  5. leelazero and google colab

    https://github.com/gcp/leela-zero/blob/master/COLAB.md 左侧菜单展开,可以查看细节

  6. windows下安装composer流程

    1.php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" 2. php -r &quo ...

  7. SPOJ:Lost and survived(multiset+并查集)

    On September 22, 2004, Oceanic Flight 815 crashed on a mysterious island somewhere in the pacific. T ...

  8. mounted

    注意 mounted 不会承诺所有的子组件也都一起被挂载.如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted: mounted: function () { t ...

  9. bzoj4750

    单调栈+前缀和 max很明显用单调栈搞,但是异或和呢?异或和我们拆位,对于每段区间的异或和[l[i]-i],[i,r[i]]答案就是0->1,1->0的乘积,但是统计的时候事实上是[l[i ...

  10. CodeForces - 504A && CodeForces - 624C && CodeForces - 2B

    Points 1. 关键要看到以度数为1的点作为突破口. 2. 关键是发现两者不同只能是a-c,而剩余的点必须为b 3. 注意0的情况.