为什么Java使用堆进行内存分配?

时间:2010-05-07 09:47:53

标签: java memory heap

我刚刚在一本java书中读到这句话,说java中的Objects驻留在堆上。 是否使用了堆,因为它是存储数据和快速检索数据的最佳方式?

我只对数据结构是初学者有所了解。我的意思是为什么不堆叠或其他东西?

7 个答案:

答案 0 :(得分:14)

堆栈问题是您只能删除最近添加的内容。这适用于局部变量,因为它们在您进入和退出函数时来来往往,但对于生命周期不遵循单个函数的任意数据则不太好。内存堆允许您随意添加和删除数据。

答案 1 :(得分:3)

仅由vm使用堆来分配和释放内存块。要访问那里的对象,您可以使用对内存块的引用(该引用位于堆栈中)。 jvm不允许直接访问内存(如在C / C ++中)。

答案 2 :(得分:2)

它是底层计算模型的工件。操作系统的内存看起来像一个大的,大部分是连续的空间,可以通过地址读取和写入数据。操作系统允许进程通过使用内存地址和读/写操作来获取内存块(一个大的连续空间,通常至少是一对K的一页),并根据需要使用它们。

java堆建立在那个基础之上,即对于程序员而言,它看起来就像是一大堆内存(当然不是,即垃圾收集通常会移动东西),他得到了“地址”(参考真的,他们写入此内存空间的数据(对象)实际上不是地址。这使您可以最大程度地灵活地构建更专业的数据结构。

请记住,它对程序员来说就像一个“堆”,因为它允许您具有必要的灵活性,但它不必如此实现。它是由垃圾收集器管理的一块内存,它有一堆数据结构用于完成它的工作,你可以或不可以考虑它的一部分,即它是由JVM使用和分配的内存,但通常只有程序员可以访问的内存才被认为是这个上下文中的“堆”。

答案 3 :(得分:1)

因为Java使用垃圾收集器来回收内存,这与C和C ++不同。在这些语言中,将堆栈用于局部变量*是有意义的。在Java中,没有(本地)变量超出范围的概念,只有它不再被引用,这使得它有资格进行垃圾收集(在某一时间有时会发生

* ,为了清楚起见,并不意味着C / C ++中没有堆,或者您无法使用malloc / new family用于分配仅在本地范围内使用的变量。

答案 4 :(得分:1)

为什么不在堆栈上存储对象?那么,当前执行的方法停止执行后,堆栈会发生什么?

答案 5 :(得分:1)

因为Java中的对象通常比创建它们的范围更长,所以为该范围创建的堆栈帧不再存在。

当创建对象的范围不再存在时,相反的分配堆空间不会自动解除分配。

答案 6 :(得分:0)

如果转义分析确定在方法返回时非本地对象不保留对该对象的引用,则Java可以在堆栈上存储对象。它不允许您声明对象存储在堆栈中。

如果Java确实允许在堆栈上显式显示对象,那么当该方法返回时会发生什么?对任何非本地对象持有的本地对象的任何引用会发生什么?

  • Java设计人员可能已经确定某些引用可能无效,如果取消引用则会导致未定义的行为。就像C / C ++中的指针一样。 Java设计人员似乎已经竭尽全力避免未定义的行为。

  • Java设计者可以指定对本地对象的所有引用都变为null。找到所有这些参考文献会很困难。并且它将导致难以发现由假定为非null的引用突然变为null的错误。包含对象引用的不可变对象是不可能的。并且设置对null的引用的通知机制必须跨线程工作。所有这些的成本远远高于本地存储的优势。

  • 语言设计师之一,James Gosling,有一个Lisp背景,这种影响在对象处理只留给垃圾收集器的想法中可见,编译器或运行时环境优化了对象处理(逃逸)分析)如果可能的话。