是通过方法推送对象时复制的对象吗?

时间:2014-01-10 09:25:21

标签: java memory garbage-collection benchmarking heap-memory

假设我的对象状态为private static Integer i = 0。假设我通过一些将i作为参数的方法推送出来,如下所示:pushThroughMethod(i)

是否i被复制到堆上并有资格进行垃圾回收?

2 个答案:

答案 0 :(得分:1)

Java原始类型(int,long,float等)但不是它们的对象(Integer,Long,Float等)是按值传递的。此外,对象的引用按值传递。虽然对象本身是通过引用传递的。

因此,如果您使用对象O调用方法x(),那么:

O o = new O(); // Create an O on the heap, put a reference to it on the stack

x(o); // Pass a copy of the reference into x, the reference still points to O

X内:

void x(O o) {
    // o is a separate reference, so if you do o = null; it does not chance the reference in the calling function.
    // but the o itself is shared, so if you do o->doSomething() the calling function will be able to see the results of doSomething().
}

在您调用pushThroughMethod(i)的示例中,创建了对i的新引用,但它指向的是Integer

i只有在所有强引用已经消失后才有资格获得垃圾收集。在这种情况下,即使pushThroughMethod()删除它对i的引用,静态引用仍将保留并阻止收集。

答案 1 :(得分:0)

您已声明了引用类型java.lang.Integer的变量。无论您分配给它的是对该类型的对象的引用。

显然,无论是否进行任何方法调用,堆上都有一个对象。

相反,如果你有一个int变量,并且你将它传递给一个带有Integer参数的方法,那么你会说Integer个实例将是正确的因为该方法调用而参与其中。

该调用是否构成Integer new 实例是JVM的内部细节,并且至少受到以下问题的限制(对HotSpot 7有效):

  • 如果值在[-128,127]范围内,则将使用缓存的Integer实例;
  • 对于其他值,可以在堆上创建新实例 ,但也可以进行堆栈分配。如果是后者,堆栈上甚至可能没有完整的对象,只有int值。所有这些都取决于JIT编译器执行的优化深度。

最后,请注意in a related question,衡量的是new Integer(1)实际生成的更快代码而不是Integer.valueOf(1)(问题是关于Character,但除此之外的故事完全相同)。