有关Java中终结器的问题

时间:2011-07-29 12:04:05

标签: java garbage-collection finalizer

假设我有以下课程

   class A {
           //some attributes 

        @override
         protected void finalize() throws Throwable {
              //do something

       }
  }


   class B extends A {

           @override
         protected void finalize() throws Throwable {
             //DONT call super.finalize() 
             //do something

       }
     }

在这种情况下会发生什么?在某些时候,垃圾收集器是否会调用调用A类的finalize方法?

调用它与在子类的finalize方法中调用A的finalize方法之间有什么不同,如果垃圾收集器无论如何都要调用它?

在什么情况下,可以不在子类中调用其父级的finalize方法?这种情况的任何一个例子?

4 个答案:

答案 0 :(得分:2)

首先,显式调用finalize()方法就像调用任何其他Java方法一样。如果您的特定类覆盖了finalize()方法,那么永远不会确定不调用父级的finalize()方法。当然,如果实现finalizer guardian pattern,则不需要在子类中显式调用父终结器。

顺便说一下,不要依赖finalize()方法来清理可以明确清除的资源(比如关闭文件句柄等),因为终结器是非确定性的。另外,请查看presentation by Bob Lee以使用Phantom引用代替终结器。

答案 1 :(得分:2)

您应该始终致电super.finalize()以防止资源泄漏。请参阅thisthis。垃圾收集器总是最多调用finalize()一次,由于多态性,只显式调用overriden方法。

请注意,甚至建议在finalize()内调用finally以确保调用它。但我会给你更好的建议:完全不依赖finalize。尽快显式关闭资源并尝试新的Java 7功能:try with resource

答案 2 :(得分:1)

不,如果您没有像任何其他方法调用一样明确使用B,则只会调用super.finalize()的finalize方法。

但是你应该注意,不调用超类的finalize方法不是一个好习惯。您可能会无意中错过关闭资源或其他内容。

答案 3 :(得分:1)

回答你的问题,

  1. 垃圾收集器会在某个时间点调用finalize()方法,但这不能保证。

  2. 垃圾收集只会在当前对象上调用finalize()。所以在B上调用finalize()不会在A上调用finalize(),除非使用super.finalize()显式调用。

  3. 如果要在对象进行垃圾回收之前进行一些清理操作,则调用
  4. finalize()方法。现在如果A和B有不同的finalize方法实现,并且B的终结不依赖于那么你不应该调用parent finalize方法。 例如,A的finalize()方法释放某些资源,专门的B类也释放某些资源(独立于As)。以类似的方式,可能有其他A的子类正在使用A的资源(因此不会覆盖A的finalize())。在这种情况下,如果从B.finalize调用super.finalize(),可能会导致麻烦,因为A持有的资源被其他子类使用。