关于Java finalize方法的访谈问题

时间:2011-05-03 01:40:36

标签: java

我遇到了关于finalize方法的困难(对我来说)Java面试问题。假设您已经给出了如下所示的finalize方法:

public void finalize()
{
     a.b = this;
}

现在给出了以下对象场景。

enter image description here

你会如何解决这个问题?如果A不是指B,那么这个问题可能会更容易,因为GC会运行,它会收集B并为B调用finalize,但这里A指的是B,所以很难。 finalize如何在这种情况下起作用?

有什么想法吗?提前致谢

4 个答案:

答案 0 :(得分:1)

非常有趣的问题。从JDK1.6 Doc,我发现这两句话: 1. finalize方法可以采取任何操作,包括使该对象再次可用于其他线程 2.对于任何给定对象,Java虚拟机永远不会多次调用finalize方法。

所以在我看来,第一次,当B通过GC收集时,如果A仍然可用于某些线程,则会调用finalize方法,然后B再次可用,这次GC不会收集B.但是因为finalize方法只会被调用一次,所以下次当GC找到B时,任何线程都无法访问,那么GC会收集B。

答案 1 :(得分:1)

考虑Java最终化的最简单方法是将每个具有终结器的对象视为状态的额外“位”。创建新对象时,此 isFinalized 位设置为false。当垃圾收集器发现具有终结器的对象无法访问时,它会检查此 isFinalized 位并仅在该对象为真时回收该对象 - 如果该对象为false,则它将运行终结器并设置该位为真。一旦设置,就无法清除该位,因此在以后的任何时候垃圾收集器都会运行,如果它无法访问,它将被收集。

答案 2 :(得分:0)

你所要求的并不完全清楚。

但是,JLS 12.6.2表示未指定对象最终确定的顺序。这意味着所有可终结类的finalize方法应设计为在以任何顺序调用时都能正常工作。

请注意,这同样适用于无法访问和终结器可访问的对象。换句话说,图表中的3个对象可以按任何顺序最终确定。


  

...如果A可以到达,B将如何被垃圾收集,以及如何为B调用finalize?

也许这是一个棘手的问题。如果A是可达的,那么B也是可达的,因此它不会被垃圾收集,并且不会调用它的终结方法。如果A 变得无法访问,那么B也是如此,两者都将被最终确定。

最终确定方法实际上取决于它属于哪个类。让我们假设它是“保证可达对象”的方法,a变量包含对A的引用:

  • GC不会调用finalize方法,因为该对象可以访问。

  • 其他一些代码可以显式调用finalize方法。如果发生这种情况,那么a.b将不再引用B,并且B将无法访问并且有资格进行最终垃圾收集,最终确定和(最终)删除。

答案 3 :(得分:0)

抱歉,如果我错了。但是对我来说,B是A的一个字段,所以A肯定需要保持对B的引用,而A持续引用A的“always-live”对象,A和B都不会是GC而且GC的问题B没有任何意义。