局部变量如何保存在内存中?

时间:2012-09-25 10:43:50

标签: java

我想知道如何在内存中放置一个局部变量?在method1中,变量是否会占用一次内存? 在method2中,每次在内存中删除旧位置后,变量是否取一个位置?

public void method1() {
    Object obj = null;
    for(.....) {
        obj = come from other-->

    }
}

public void method2() {
    for(.....) {
        Object obj = come from other-->
    }
}

5 个答案:

答案 0 :(得分:2)

您有一个局部变量,可能在寄存器中或一次在内存中。

您还有一个局部变量引用的对象。这将在两种情况下在每次迭代时创建。

它们实际上是相同的,除非我更喜欢第二种情况,因为它可以缩小局部变量的范围。

答案 1 :(得分:1)

每个方法调用都与存储在调用堆栈上的激活记录相关联。激活记录保存对应于方法级别变量的堆中的内存块的引用。一旦方法调用返回给调用者,该激活记录将从堆栈中删除,并且内存引用可能被垃圾收集。

在你的情况下,

  1. 第一种方法中的obj,它的引用存储在调用堆栈中,实际内存在堆上,每次方法调用都会执行一次。
  2. 第二种方法中for循环中的obj为每次迭代创建一次,并在每次迭代结束时超出范围。因此,堆的引用和内存将为每次迭代分配。

答案 2 :(得分:1)

局部变量通常(除非例如优化掉)保留在堆栈存储器中。但它们只能存储原始值或引用。引用的对象本身通常在堆上分配(经受任何JIT优化)。

请参阅Stack based memory allocation (Wikipedia)Heap based memory allocation (Wikipedia)

在堆栈上存储值非常便宜。类似于函数调用,将返回指针存储在堆栈中。它不需要增加堆栈指针(并且您可以想象增加专用CPU寄存器的速度很快!)

对象本身是不同的。请注意,理论上,某些Java编译器或JIT可能能够更好地优化您的第二个代码,因为您清楚地指出下一次迭代不需要该值。 (一个更好的编译器应该能够自己解决这个问题。)

通常,现代编译器应该在优化两种情况后生成相同的机器代码。 (这可能发生在JIT编译器中,因此Java字节码可能仍然显示差异)。

无论如何:不要试图通过重用本地变量来过度优化。相反,编写显式代码并让编译器进行优化。通过在循环中使用一个新变量,可以明确表示它不会在任何地方重复使用。这可以防止一些编程错误!

答案 3 :(得分:0)

我相信在这两种情况下,每次迭代都会在内存中创建一个新的Object。由垃圾收集器注意除了最“最近”的对象之外没有任何引用。

答案 4 :(得分:0)

method1和method2中的对象将放在堆中,但是java编译器执行 Escape analysis 以确定我们需要在方法执行后释放这种对象。转义分析在Java Standard Edition 6中实现