此代码是我的课程测试的一部分 -
class Bar { }
class Test
{
Bar doBar()
{
Bar b = new Bar(); /* Line 6 */
return b; /* Line 7 */
}
public static void main (String args[])
{
Test t = new Test(); /* Line 11 */
Bar newBar = t.doBar(); /* Line 12 */
System.out.println("newBar");
newBar = new Bar(); /* Line 14 */
System.out.println("finishing"); /* Line 15 */
}
}
在Bar
上创建的line 6
对象在什么时候有资格进行垃圾回收?是doBar()
完成的时候吗?
答案 0 :(得分:2)
当对新Bar
对象的新引用分配给第14行的变量Bar
时,对第6行创建的newBar
对象的所有引用都将被销毁。因此{{在第6行创建的对象有资格在第14行之后进行垃圾收集。
Bar
完成时不会,因为doBar()
方法中的引用在第7行返回并存储在第12行的doBar()
中。此保留对象在线创建6。
答案 1 :(得分:1)
这种问题似乎在向初学者教授Java时非常流行,但完全是胡说八道。虽然answer like this非常适合制作,但无论是谁发明了这个问题,快乐,在深入挖掘时都是不正确的:
对局部变量中保存的对象的引用不会阻止对象被垃圾回收。如果后续代码没有触及它们,则仍然可以认为这些对象不可达,这不是理论问题。如“finalize() called on strongly reachable object in Java 8”中所示,即使正在执行该对象的方法也不会妨碍其收集,如果后来没有触及该实例。
由于在您的示例代码中,对象不包含任何数据,因此很明显它们根本不会被触及,这意味着它们可能随时被收集,具体取决于JVM的优化状态。代码也可能被优化到一定程度,它只执行两个print语句的可见副作用,换句话说,根本就不会创建对象。
这由The Java® Language Specification, § 12.6.1. Implementing Finalization支持:
可以设计优化程序的转换,以减少可达到的对象数量,使其少于可以被认为可达的对象数量。例如,Java编译器或代码生成器可以选择将不再用于
null
的变量或参数设置为使得此类对象的存储可能更快地回收。如果对象字段中的值存储在寄存器中,则会出现另一个示例。然后程序可以访问寄存器而不是对象,并且永远不会再次访问对象。这意味着该对象是垃圾。 ...
实际上,由于这是main
方法中的简单短代码,最常见的情况是代码运行未经优化,但在短时间内不会发生垃圾回收。
这导致了提出这些问题的另一个原因是无稽之谈。当一个对象天真地被认为无法访问时找到正确的点可能很有挑战性,不可能猜出优化器何时以及如何影响结果,但垃圾收集的整个目的是开发人员不必担心这一点。
答案 2 :(得分:0)
执行lin 14分配后。此时,不存在对第6行的Bar对象的引用。
答案 3 :(得分:0)
我同意jiltedpotato(这将是第14行之后)。当对象丢失或丢弃时,对象有资格进行垃圾回收。
答案 4 :(得分:0)
就像没有对象的引用一样简单就有资格进行垃圾收集但是什么时候才能完全收集它取决于GC算法。