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

PM *_*7-1 10 java garbage-collection jvm memory-management object

我的问题与:

当我们在代码中有这样的事情时,实际发生了什么:

 (new SomeClass()).longMethod();
Run Code Online (Sandbox Code Playgroud)

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

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

它可能是相同的

{ 
  // very local scope
  SomeClass throwAwayRef = new SomeClass();
  throwAwayRef.longMethod();
}
Run Code Online (Sandbox Code Playgroud)

ars*_*jii 6

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

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

(new SomeClass()).longMethod();
Run Code Online (Sandbox Code Playgroud)

是不一样的

{ 
  // very local scope
  SomeClass throwAwayRef = new SomeClass();
  throwAwayRef.longMethod();
}
Run Code Online (Sandbox Code Playgroud)

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


参考:


Ada*_*ley 1

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

直接来自甲骨文:

要访问字段,您可以使用对象的命名引用(如前面的示例所示),也可以使用返回对象引用的任何表达式。回想一下,new 运算符返回对对象的引用。因此,您可以使用 new 返回的值来访问新对象的字段:

int height = new Rectangle().height;

该语句创建一个新的 Rectangle 对象并立即获取其高度。本质上,该语句计算矩形的默认高度。请注意,执行此语句后,程序不再拥有对创建的 Rectangle 的引用,因为程序从未在任何地方存储该引用。该对象是未引用的,其资源可以由 Java 虚拟机自由回收。

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

  • 请提供更多证据或示例 (3认同)