我有个问题
例如,当我在方法中声明变量时会发生什么。
无效我的方法(){ 运送 myShip = new Ship(); }
myShip 引用在哪里分配,在堆栈中还是在堆中?
我认为在堆栈中,但我很困惑,因为我正在阅读 J2ME 游戏编程书“Java 类被实例化到 Java 堆上”
所有java类?
提前致谢
我有个问题
例如,当我在方法中声明变量时会发生什么。
无效我的方法(){ 运送 myShip = new Ship(); }
myShip 引用在哪里分配,在堆栈中还是在堆中?
我认为在堆栈中,但我很困惑,因为我正在阅读 J2ME 游戏编程书“Java 类被实例化到 Java 堆上”
所有java类?
提前致谢
myShip
是对一个Ship
对象的引用,myShip
是在方法调用栈上的,也就是所谓的“栈”。当一个方法被调用时,一块内存被压入栈顶,该内存块有空间用于该方法的所有基元(int、float、boolean 等)和对象引用,其中包括方法参数。堆是为实际对象分配内存的地方。
所以myShip
在堆栈上,Ship
对象在堆上。
请注意,每个线程都有自己的堆栈,但共享堆。
Java 做的事情确实有点不同。引用基本上在堆栈上。对象的内存在堆中分配。但是,可分配内存的实现方式与 C/C++ 模型中堆的实现方式不太一样。
当您像这样创建一个新对象时,它会有效地将名称放入该范围的引用表中。这很像 C++ 中指向对象的指针。当它超出范围时,该引用将丢失;分配的内存不再被引用,并且可以被垃圾回收。
目前,所有 Java 对象都在堆上分配。有传言说 Java 7 可能会进行逃逸分析并能够在堆栈上分配,但我不知道该提案是否最终确定。这是 RFE。
编辑:显然,它已经在 JDK 7 的早期版本中。(文章说它也会在 JDK 6u14 中,但我找不到确认。)
从概念上讲,对象在“堆”上。然后,因为它是方法本地引用,所以实际引用将在堆栈上。“the”堆栈,我们指的是至少在 Sun 的 VM 的情况下,本机线程堆栈(即 C 中的局部变量将被分配的同一堆栈),但我认为这实际上不是一个要求(JVM只需要在每个方法调用上分配一些“堆栈帧”的抽象概念,无论是否来自本机堆栈)。
但是......在现代虚拟机上(公认的可能是更简单的嵌入式/mpbile 虚拟机除外),实际上没有“堆”之类的东西。在实践中,有各种堆区域。其中最简单的通常几乎就像一个“迷你堆栈”,旨在快速分配不会长时间徘徊并且可能几乎可以立即解除分配的对象。
正如另一张海报所提到的,高度优化的 JVM原则上可以在堆栈上分配对象数据,并且对此有明确的建议。虽然,正如其中一个参考文献中提到的那样,对此的批评是快速“伊甸园”堆几乎就像一个堆栈(只是不是“那个”堆栈)。