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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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