0

我想知道如何在内存中放置一个局部变量?在方法 1 中,变量是否会一次进入内存?在方法2中,每次删除内存中的旧位置后,变量是否会占一个位置?

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

    }
}

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

5 回答 5

2

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

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

它们实际上是相同的,但如果可能的话,我更喜欢第二种情况,因为它缩小了局部变量的范围。

于 2012-09-25T10:45:53.943 回答
1

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

在你的情况下,

  1. obj第一种方法中,它的引用存储在调用堆栈中,实际内存在堆上,每次方法调用都会执行一次。
  2. 第二种方法中的objfor 循环在每次迭代中创建一次,并在每次迭代结束时超出范围。因此,每次迭代都会分配堆上的引用和内存。
于 2012-09-25T10:48:51.033 回答
1

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

请参阅基于堆栈的内存分配(维基百科)基于堆的内存分配(维基百科)

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

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

一般来说,现代编译器应该在对这两种情况进行优化后生成相同的机器代码。(这可能发生在 JIT 编译器中,因此 Java 字节码可能仍会显示差异)。

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

于 2012-09-25T10:51:36.953 回答
0

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

于 2012-09-25T10:48:41.817 回答
0

method1 和 method2 中的对象会被放到堆中,但是 java 编译器会进行Escape 分析来判断我们是否需要在方法执行后释放这种对象。逃逸分析在 Java 标准版 6 中实现

于 2012-09-25T10:51:47.820 回答