没有参考的新对象的生命周期

时间:2015-06-17 17:18:16

标签: java object memory-management garbage-collection jvm

我的问题与:

有关

当我们的代码中出现类似内容时,会发生什么:

 (new SomeClass()).longMethod();

是否还有某种未命名的(强?)引用指向堆放在堆上的新创建的对象?

如果Stack上没有任何内容,那么垃圾收集器如何知道在方法持续时间内保留对象?

是否可能与

相同
{ 
  // very local scope
  SomeClass throwAwayRef = new SomeClass();
  throwAwayRef.longMethod();
}

3 个答案:

答案 0 :(得分:6)

您可以查看字节码以获取洞察力:

   0: new           #16                 // class SomeClass
   3: dup
   4: invokespecial #18                 // Method SomeClass."<init>":()V
   7: invokevirtual #19                 // Method SomeClass.longMethod:()V
  • new实际上分配了对象,对象的引用被推送到堆栈上。
  • dup复制堆栈顶部;现在,前两个堆栈项是对新创建的对象的引用。
  • invokespecial这里调用SomeClass的构造函数,弹出堆栈;现在,堆栈只包含对SomeClass实例的单个引用。该实例未进行GCed,因为堆栈上存在对它的引用。
  • invokevirtual来电longMethod。同样,实例不是GCed,因为对它的引用仍然存在于堆栈上(并且在方法完成后弹出,之后 符合GC的条件)。
(new SomeClass()).longMethod();

不同
{ 
  // very local scope
  SomeClass throwAwayRef = new SomeClass();
  throwAwayRef.longMethod();
}

在字节码级别,因为后者涉及astoreaload。但是,这两者肯定在功能上是等价的。 SomeClass完成后,longMethod实例仍符合GC条件(执行invokevirtual时,两个代码段的堆栈看起来相同)。

<强>参考:

答案 1 :(得分:3)

是,

new SomeClass().longMethod();

实际上是相同的,特别是从垃圾收集的角度来看:

{
    SomeClass throwAwayRef = new SomeClass();
    throwAwayRef.longMethod();
}

内联版本具有对新对象的隐式引用(在堆栈上)。一旦方法调用结束,它就可用于垃圾收集。

答案 2 :(得分:1)

是的,堆栈上存在对新对象的引用。

直接来自Oracle:

  

要访问字段,您可以使用对象的命名引用,如   前面的示例,或者您可以使用任何返回的表达式   对象参考。回想一下new运算符返回一个引用   一个东西。所以你可以使用new返回的值来访问a   新对象的字段:

     

int height = new Rectangle().height;

     

此语句创建一个新的   Rectangle对象并立即获得其高度。从本质上讲,   statement计算Rectangle的默认高度。 请注意   在此声明执行后,该程序不再具有   引用创建的Rectangle,因为程序从未存储过   任何地方的参考。该对象未被引用及其资源   可以通过Java虚拟机自由回收。

来源:https://docs.oracle.com/javase/tutorial/java/javaOO/usingobject.html