我遇到了关于finalize方法的困难(对我来说)Java面试问题。假设您已经给出了如下所示的finalize方法:
public void finalize()
{
a.b = this;
}
现在给出了以下对象场景。
你会如何解决这个问题?如果A不是指B,那么这个问题可能会更容易,因为GC会运行,它会收集B并为B调用finalize,但这里A指的是B,所以很难。 finalize如何在这种情况下起作用?
有什么想法吗?提前致谢
答案 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没有任何意义。