java中怎么理解“堆空间”和“栈空间”?

榨菜大叔@ 2010-01-03 10:29:30
一:java中怎么理解“堆空间”和“栈空间”?
二:还有实例化对象的时候是怎样开辟内存空间的?
三:引用对象内存怎么分配和指向?

这些数据结构问题老是犯浑,平时都不没接触过,面试问到一句都说不出,请知道的朋友帮忙解释下。
能画个内存指向图更好....
...全文
1400 47 打赏 收藏 转发到动态 举报
写回复
用AI写文章
47 条回复
切换为时间正序
请发表友善的回复…
发表回复
笑一笑 2012-02-21
  • 打赏
  • 举报
回复
1、一看new 关键字就分配内存和实例化
1、栈是分配内存地址,而堆空间是分配内存,有栈指向堆空间里面的对象
superhill 2012-02-21
  • 打赏
  • 举报
回复
同意2楼说法

[Quote=引用 2 楼 java_cxrs 的回复:]

首先建议你看 尚学堂马士兵老师的 J2SE视频 主要看面向对象那章 通过画图 很快能理解这些
堆空间 就是用来存储对象的
栈空间是用来存储一些变量的 用完后会通过垃圾收集器自动清楚
引用对象通过类似指针的方法来指
[/Quote]
神经斌 2012-02-21
  • 打赏
  • 举报
回复
[Quote=引用 44 楼 d846674104 的回复:]

你连这个都不会,你学过数据结构没,懒得理你,以后没事干就插百度去,别在这上面丢人,这是个圣神的地方!
[/Quote]

不要这样,问道有先后,能帮就帮,帮不了就一起学习,这里是神圣的地方,我不反对,但是这里也是学习的地方,是权威的地方,百度上鱼龙混杂、参差不齐,相比之下有问题还是在这里提比较好,这里热心的人、牛人都很多,谁都有困惑的时候,要与人为善。
d846674104 2012-02-20
  • 打赏
  • 举报
回复
你连这个都不会,你学过数据结构没,懒得理你,以后没事干就插百度去,别在这上面丢人,这是个圣神的地方!
兰再晨 2012-02-20
  • 打赏
  • 举报
回复
Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。
  堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。
  这也是 Java 比较占内存的原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!
AlanZhang 2012-02-20
  • 打赏
  • 举报
回复
建议看看<<Thinking in java>>书中“存储到什么地方”那块知识。
推荐资源下载:http://download.csdn.net/detail/qmx_zhq/3410905
zhuyouyong 2012-02-20
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 java_cxrs 的回复:]

首先建议你看 尚学堂马士兵老师的 J2SE视频 主要看面向对象那章 通过画图 很快能理解这些
堆空间 就是用来存储对象的
栈空间是用来存储一些变量的 用完后会通过垃圾收集器自动清楚
引用对象通过类似指针的方法来指
[/Quote]这哥们说的在理!
tingyuing 2012-02-20
  • 打赏
  • 举报
回复
mark
cwhe007 2010-01-08
  • 打赏
  • 举报
回复
什么是堆 ?
当对象你把他NEW出来的时候 JVM就内存当中开辟了一块空间 这块空间就叫做堆 ,所有NEW出来的东西都放在堆里面
什么是栈 ?
除了NEW出来的东西 其他的放到栈里面
charles361 2010-01-06
  • 打赏
  • 举报
回复
栈(stack):局部变量,引用变量
堆(heap):Class ,Array
zsyok 2010-01-06
  • 打赏
  • 举报
回复
学习了!
web 网站建设
songzhd 2010-01-06
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 spiniper 的回复:]
首先回2楼,不要看中国人写得书,虽然中国文化源远流长,但是计算机这方面还是不要看中国人写的,毕竟有差距,而且中国人写的书很多都存在误导。
回楼主,首先解释一下虚拟机内存:
java虚拟机存在方法区,堆空间与栈空间,定义是这样的,虚拟机具体实现完全可以把它们分开在不同内存中,也可以把它们放在同一段内存中。
方法区存放类与方法。
堆空间存放实例化的对象。
栈空间有两种,一种是方法栈,虚拟机会为每个线程所调用的方法申请空间,而这个栈就是这些空间,另外一个是操作数栈,两个局部变量或者成员变量需要进行处理的时候,执行语句会吧这两个变量的值放入操作数栈中进行处理,处理完成以后会将处理结果弹出栈。
了解了这些后其实那些问题都不难:
第一个问题上面说得很清楚了。
第二个问题,当虚拟机生产对象的时候会申请内存空间(怎么申请的,你去看汇编程序设计以及寄存器寻址方式),然后如果引用是静态成员变量,则引用放在方法区中,如果引用是成员变量则放在堆中,如果引用是局部变量,则成为局部变量索引(局部变量没有变量名称,它只是一个索引项)。
第三个问题,虚拟机规范没有规定引用应该去怎么实现,如今应用大致有两种实现方式,一种是引用直接就是一个指向堆内存的指针,另外一个是引用指向方法区类对象映射表中的某个项,映射表中的项再以指针的形式指向堆内存空间,具体实现可能还有更多情况,所以这个问题你不必太过于探讨。

[/Quote]

学习了。
tiamay 2010-01-06
  • 打赏
  • 举报
回复
1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。

2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享,详见第3点。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
klose1118 2010-01-06
  • 打赏
  • 举报
回复
mark
不白吃饭 2010-01-06
  • 打赏
  • 举报
回复
有牛人,标记下,吃完饭回来读。。
sunwayMike 2010-01-06
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 xcc19891220 的回复:]
引用 2 楼 java_cxrs 的回复:
首先建议你看 尚学堂马士兵老师的 J2SE视频 主要看面向对象那章 通过画图 很快能理解这些
堆空间 就是用来存储对象的
栈空间是用来存储一些变量的 用完后会通过垃圾收集器自动清楚
引用对象通过类似指针的方法来指

尚学堂的东西真的很不错啊,我就一直学校呢,讲的很不错哦!!都是免费的...
看过之后保证你能了解,我懂但是不好解释..
.
[/Quote]
我赞成!
jinhaize 2010-01-05
  • 打赏
  • 举报
回复
马士兵的视频将的很清晰,当年就是看了之后现在都受益的。
KingWolfOfSky 2010-01-05
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 spiniper 的回复:]
首先回2楼,不要看中国人写得书,虽然中国文化源远流长,但是计算机这方面还是不要看中国人写的,毕竟有差距,而且中国人写的书很多都存在误导。
回楼主,首先解释一下虚拟机内存:
java虚拟机存在方法区,堆空间与栈空间,定义是这样的,虚拟机具体实现完全可以把它们分开在不同内存中,也可以把它们放在同一段内存中。
方法区存放类与方法。
堆空间存放实例化的对象。
栈空间有两种,一种是方法栈,虚拟机会为每个线程所调用的方法申请空间,而这个栈就是这些空间,另外一个是操作数栈,两个局部变量或者成员变量需要进行处理的时候,执行语句会吧这两个变量的值放入操作数栈中进行处理,处理完成以后会将处理结果弹出栈。
了解了这些后其实那些问题都不难:
第一个问题上面说得很清楚了。
第二个问题,当虚拟机生产对象的时候会申请内存空间(怎么申请的,你去看汇编程序设计以及寄存器寻址方式),然后如果引用是静态成员变量,则引用放在方法区中,如果引用是成员变量则放在堆中,如果引用是局部变量,则成为局部变量索引(局部变量没有变量名称,它只是一个索引项)。
第三个问题,虚拟机规范没有规定引用应该去怎么实现,如今应用大致有两种实现方式,一种是引用直接就是一个指向堆内存的指针,另外一个是引用指向方法区类对象映射表中的某个项,映射表中的项再以指针的形式指向堆内存空间,具体实现可能还有更多情况,所以这个问题你不必太过于探讨。
[/Quote]

6楼的说法基本上是对的,而且深有同感,部分中国人的书都是你抄我的,我抄你的,结果误导了一大批人,但也不是不要看中国人写得书,我觉得侯捷写的书就很好,最后推荐楼主看看《Java虚拟机规范》和《深入Java虚拟机》
KingWolfOfSky 2010-01-05
  • 打赏
  • 举报
回复
栈内存: 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 栈内存主要存放的是基本类型类型的数据 如、( int, short, long, byte, float, double, boolean, char) 和对象句柄。并没有有String基本类型、在栈内存的数据的大小及生存周期是必须确定的、其优点是寄存速度快、、栈数据可以共享、缺点是数据固定、不够灵活。 栈的共享: String a = "abc"; String b = "abc"; System.out.println(a==b); 结果为true 这就说明了a b其实指向同一个值 注意,我们这里并不用a.equals(b);的方式,因为这将比较两个字符串的值是否相等。==号,根据JDK的说明,只有在两个引用都指向了同一个对象时才返回真值。而我们在这里要看的是,a与b是否都指向了同一个对象。 结果说明,JVM创建了两个引用a和b,但只创建了一个对象,而且两个引用都指向了这个对象。





首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有abc这个值,如果没找到,就将abc存放进来,然后将a指向abc。接着处理String b = "abc";在创建完b的引用变量后,因为在栈中已经有abc这个值,便将b直接指向abc。这样,就出现了a与b同时指向abc

貌似不太对,看看这个

public static void main(java.lang.String[] args);
0 ldc <String "abc"> [16]
2 astore_1 [aString]
3 ldc <String "abc"> [16]
5 astore_2 [bString]
6 return

javac对.java文件进行处理,最后生成Class文件的字节码表示时,会同时生成一个常量池结构。在将数据放入常量池时,会对重复的数据进行过滤(其实是一个Map),保证值保存一份。
其实他是放在常量池里面的,而不是栈里面


特别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完a与b的值后,再令a=abcd;那么,b不会等于abcd,还是等于abc。在编译器内部,遇到a= abcd;时,它就会重新搜索栈中是否有abcd的字面值,如果没有,重新开辟地址存放abcd的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。 堆内存: 堆内存用来存放所有new 创建的对象和 数组的数据、 String a = new String ("abc"); String b = "abc"; System.out.println(a==b); //False String a = new String ("abc"); String b = new String ("abc"); System.out.println(a==b); //False 创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。
借我那把枪吧 2010-01-05
  • 打赏
  • 举报
回复
复习一下
加载更多回复(27)

62,621

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧