java面试 内存中堆和栈的区别

java中的内存,分为两种,一为堆内存,二为栈内存。

栈内存

在函数中定义的基本类型的变量和对象的引用变量都是在函数的栈内存中分配。
当在一段代码块中声明了一个变量时,java就会在栈内存中为这个变量分配内存空间,当超过变量的作用域之后,java也会自动释放为该变量分配的空间,而这个回收的空间可以即刻用作他用。

堆内存

堆内存用于存放由new创建的对象和数组。
在堆内存中分配的内存空间,由java虚拟机自动垃圾回收器来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,变量的值就等于数组或对象在堆内存中的首地址,而这个栈中的特殊变量,也就成为数组或对象的引用变量。以后可以在程序中使用栈内存中的引用变量访问堆内存中的数组或对象了。引用变量相当于是为数组或对象起的一个别名,或者是代号。
数组和对象在没有引用变量指向它的时候,才变成垃圾,不能被继续使用,但是仍然会占用堆内存空间,而后在一个不确定的时间内,由java虚拟机自动垃圾回收器回收,这也是java程序为什么会占用很大内存的原因。


一、 java中的内存分配策略及堆和栈的比较

1. 内存分配策略

根据编译原理的观点,程序运行时的内存分配,有三种策略,分别为静态的堆式的栈式的
静态存储分配指的是在编译时就能确定每个数据目标在运行时的存储空间需求,因而在编译时就给它们分配了固定的内存空间。这种分配方式要求程序代码中不能有可变数据结构(例如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译时编译程序无法准确计算所需的存储空间大小。
栈式存储分配也可以成为动态存储分配,是由一个类似于堆栈的运行栈来实现的。和静态存储分配相反,在栈式分配方案中,程序对于存储空间的需要在编译时是未知的,只有在运行的时候才能知道。但是规定在运行进入一个程序模块时,必须要知道该程序模块所需的数据区大小才能为其分配内存。同我们日常了解的栈一致,栈式存储分配遵照先进后出的原则进行分配。
堆式存储分配专门负责在编译时或运行时程序模块入口处都无法确定存储要求的数据结构的分配,比如可变长度串和对象实例。堆内存由大片的可利用块或空闲块组成,堆中的内存也可以根据任意的顺序进行分配和释放。

堆和栈的比较

从通俗化的角度来说,堆是用来存放对象的,栈是用来存放执行程序的
在编程中,例如在C/C++中,所有的方法调用都是通过栈来进行的,所有的局部变量、形式参数也都是通过栈来分配内存的。使用的时候,根据栈的工作原理,从栈顶向上用即可,Stack Pointer会自动指引程序到存储位置,程序只需要进行存储即可。退出函数的时候,修改栈指针即可将栈中存储的内容销毁。这种模块速度最快,适合用户存储执行程序。但是应当注意的是,在进行内存分配是,比如为一个即将要调用的程序模块分配数据区时,应当实现知道这个所需数据区的大小,也就是说虽然分配工作是在运行程序的时候进行的,但是分配的大小是在运行程序之前就知道的,这个是编译时确定的,而不是运行时。
堆是应用程序在运行过程中请求操作系统给分配的内存,由于是操作系统管理的内存分配,所以在分配和销毁是都需要占用时间,因此堆的工作效率比较低。但是堆的优点在于,编译器不需要知道从堆中分配了多少的内存空间,也不需要知道存储的数据要在堆中停留多长的时间,这也就使得用堆来保存数据有着更大的灵活性。事实上,面向对象的多态性的实现,堆内存的分配必不可少,因为多态对象所需的数据区大小只有在运行时确定了对象以后才能知道。在java中,创建对象只需要使用new关键字即可,执行这些代码时,就会在堆中自动进行数据的保存。也就是因为这种灵活分配存储空间的特性,堆内存分配的工作效率不高。

JVM中的堆和栈

堆和栈都是java用来在内存中存放数据的地方,与C++不同的是,java自动管理堆和栈,程序员不能自行设置堆和栈。
java中的堆就是运行时存储数据的区域,类的实例对象可以通过new、new Array等指令建立从中分配空间,这些空间不需要程序代码来显式释放。堆是由jvm自动垃圾回收器负责的,堆的优势是可以动态的分配内存大小,生存周期也不用实现告诉编译器,因为空间是在运行时动态进行内存分配的。如果堆中的数据确认为垃圾,则jvm的自动垃圾回收器汇自动回收相应的空间。但是缺点是,由于实在运行时动态进行空间分配,存取速度较慢。
栈的优势是:存取的速度都比堆要快,仅次于寄存器。栈数据可以共享,但是缺点时,栈空间中的数据大小和生存期必须是确定的,缺乏灵活性。栈主要存放一些基本类型的变量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, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。

参考:http://www.cnblogs.com/whgw/archive/2011/09/29/2194997.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,015评论 11 349
  • Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数...
    keyu88888阅读 1,271评论 3 47
  • Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数...
    杀小贼阅读 345评论 0 1
  • 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 当在一段代码块定义一个变量时,Java就...
    木有鱼丸啦阅读 524评论 0 0
  • 又到了考博的时候,不知道各位报考的同学们是否需要了解以下博士生的生活呢? 每个人的生活都是不一样的,每个博士的生活...
    沐_心阅读 1,776评论 2 3