16

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

我只知道数据结构是初学者。我的意思是为什么不堆叠或其他东西?

4

7 回答 7

15

堆栈的问题在于您只能删除最近添加的内容。这对局部变量很有效,因为它们在您进入和退出函数时来来去去,但对于生命周期不遵循单个函数的任意数据来说就不那么好了。内存堆允许您随意添加和删除数据。

于 2010-05-07T09:53:03.327 回答
3

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

于 2010-05-07T09:55:00.123 回答
2

它是底层计算模型的产物。操作系统的内存看起来像一个大的,大部分是连续的空间,可以在其中按地址读取和写入数据。操作系统允许进程通过使用内存地址和读/写操作来获取一块内存(一个大的连续空间,通常至少是几 K 的一页)并随意处理。

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

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

于 2010-05-07T10:09:02.837 回答
1

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

*为清楚起见,这并不意味着 C/C++ 中没有堆,或者您不能使用malloc/new系列来分配仅在本地范围内使用的变量。

于 2010-05-07T09:52:58.527 回答
1

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

于 2010-05-07T09:53:40.880 回答
1

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

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

于 2010-05-07T09:58:04.077 回答
0

Java 可以将对象存储在堆栈上,前提是它进行了转义分析,确定在方法返回时非本地对象没有保留对对象的引用。它不允许您声明对象存储在堆栈中。

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

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

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

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

于 2014-07-11T10:08:35.633 回答