在堆栈中还是在堆中分配变量引用的位置?

时间:2009-05-17 02:39:13

标签: java concurrency stack heap

我有一个问题

例如,当我在方法中声明变量时会发生什么。

void myMethod() {
    Ship myShip = new Ship();
}

在堆栈中还是在堆中分配myShip引用的位置?

我认为在堆栈中我很困惑,因为我正在阅读J2ME游戏编程书 “Java类被实例化到Java堆上”

所有java clases?

提前致谢

4 个答案:

答案 0 :(得分:24)

myShip是对Ship对象的引用,myShip位于方法调用堆栈上,称为“堆栈”。当一个方法被调用时,一块内存被推到堆栈顶部,该内存块有所有基元(int,float,boolean等)的空间和方法的对象引用,其中包括方法参数。堆是分配实际对象的内存的地方。

所以myShip在堆栈上,Ship对象在堆上。

注意每个线程都有自己的堆栈但共享堆。

答案 1 :(得分:13)

Java确实做的事情有点不同。 引用基本上在堆栈上。对象的内存分配在堆的传递中。但是,可分配内存的实现与在C / C ++模型中实现堆的方式不太一样。

当您创建这样的新对象时,它会有效地将名称放入该范围的引用表中。这就像是指向C ++中对象的指针。当它超出范围时,该引用就会丢失;分配的内存不再被引用,可以被垃圾收集。

答案 2 :(得分:6)

目前,所有Java对象都在堆上分配。有人说Java 7可能会进行转义分析并能够在堆栈上进行分配,但我不知道该提案是否已经完成。 Here's the RFE

编辑:显然,它是already in early builds of JDK 7。 (文章说它也将在JDK 6u14中,但我找不到确认。)

答案 3 :(得分:3)

从理论上讲,该对象继续“堆”。然后,因为它是方法本地引用,实际引用将在堆栈上。对于“堆栈”,我们指的是至少在Sun的VM情况下本机线程堆栈(即C中的本地变量将被分配的堆栈),但我不认为这实际上是一个要求(JVM)只需要在每次方法调用时分配一些“堆栈帧”的抽象概念,无论是否来自本机堆栈。

但是......在现代虚拟机上(不可否认的是,更简单的嵌入式/ mpbile虚拟机可能除外),实际上没有“堆”这样的东西。实际上,有各种堆区域。 其中最简单的通常几乎就像是一个“迷你堆栈”,旨在快速分配不会长时间闲置的对象,并且几乎可以一次性解除分配。

正如另一张海报所提到的,高度优化的JVM 原则上原则上可以在堆栈上分配对象数据,并且有明确的建议。虽然,正如其中一篇文章中所提到的,对此的批评是,快速的“伊甸园”堆几乎就像一个堆栈(只是不是“堆栈”)。