为什么我们使用堆内存,我们可以使用堆内存吗?
在阅读答案后,我脑海中浮现出另一个问题 1)有没有其他类型的记忆我们可以想到替代堆和堆栈?
我遇到了字符串池,是与堆或堆栈关联的内存吗?
答案 0 :(得分:11)
好吧,如果你想使用对象,你有来使用堆。对象本质上是堆栈(或其他对象内部)与堆中内存块的指针。
与可以将对象放在堆栈或堆上的C ++不同,Java会以不同的方式执行操作。
即使在C ++中,最好将堆用于必须比它们创建的函数更长的对象。你可能可以避免它但你可能会发现自己遇到了性能问题复制构造函数。
关于你的编辑:
还有其他类型的记忆我们可以想到替代Heap和Stack吗?
当然有:静态数据成员,每个类只有一个而不是每个实例化对象的成员必须去某个地方。这些不能在堆栈中,因为它们可能会在您退出函数时消失。而且它们不属于特定的对象。
这些(至少在Sun / Oracle JVM中)进入Method区域。
此外,你不应该想到有一个堆栈。每个线程在创建时都有自己的堆栈。
还有本机(非Java)调用的运行时常量池和堆栈。
有关该方面的JVM内部here有很多信息,但请记住,逻辑机器和实现之间可能存在区别。
答案 1 :(得分:2)
堆内存是Java的核心。所有对象都在堆上分配,而局部变量只包含对它们的引用(实质上是指针)。 C#允许您拥有堆栈中的对象(值类型)。 Java选择不从C ++中借用它,部分原因是为了简化语言。
在各种语言中,堆内存是提供任意大小的长寿命对象的方法。
答案 2 :(得分:2)
我们可以使用堆栈内存吗?
基本上没有。
在Java中,堆栈内存仅用于方法的参数和局部变量(以及与本讨论无关的一些隐藏的簿记信息)。对于那些变量,只有原始类型只使用堆栈内存。任何对象或数组都表示为对堆上某些东西的引用,而Java则无法在堆栈上分配对象或数组。
[旁白:理论上可以使用原始类型和递归静态方法在Java中执行任何计算。但是,它会非常混乱。即使向控制台写一条简单的消息也会导致您的应用程序导致在堆上分配对象。所以我们可以认为这是完全不切实际的。]
答案 3 :(得分:1)
在JVM中,它使用线程本地分配缓冲区或(TLAB)而不是对象的线程本地堆栈。这提供了堆栈的许多性能优势,而开发人员无需担心对象是否在是否堆叠。
答案 4 :(得分:1)
堆内存用于在Java中存储对象。无论如何,在代码中创建对象。 例如作为成员变量,局部变量或类变量,它们总是在Java中的堆空间内创建。 如果堆栈中没有用于存储函数调用或局部变量的内存,JVM将抛出java.lang.StackOverFlowError, 如果没有更多的堆空间来创建对象,JVM将抛出 java.lang.OutOfMemoryError Java堆空间。
答案 5 :(得分:0)
另一个需要考虑的重要因素是范围界定。如果要在堆栈上分配所有对象,那么随着堆栈帧的推出,它们将脱离上下文。通俗地说,将堆栈视为转储,它存储当前在范围内的子例程/方法的本地所有变量值和对象引用。一旦完成执行(或方法超出范围),那么其中的所有内容都将丢失。
答案 6 :(得分:0)
它使编译器更容易管理大型和/或动态大小的变量 - 它们仍然在调用堆栈上占用小的常量存储 - 即4个字节(堆指针)。