覆盖Object类的finalize()方法有什么用?

时间:2011-04-12 13:12:59

标签: java garbage-collection

据我所知,在java中,如果我们想手动调用垃圾收集器,我们可以做System.gc()。
1.我们在覆盖的finalize()方法中进行的操作是什么?
2.如果我们想手动调用JVM垃圾收集器,是否需要覆盖finalize()方法?

8 个答案:

答案 0 :(得分:9)

  

我们在覆盖的finalize()方法中执行的操作是什么?

手动(通过一些本机调用)备用的空闲内存,即不由GC管理。这是一个非常罕见的情况。 有些人还在那里检查,与对象相关的其他资源已经被释放 - 但它仅用于调试目的而且不太可靠。
你必须记住:

  1. finalize是关于记忆和唯一的记忆。
  2. 您无法控制何时调用它,甚至是否可以调用它。
  3. 所以从来没有放在那里释放任何其他资源(如文件句柄,锁)。所有这些资源必须手动释放 覆盖finalize与调用System.gc()无关。

答案 1 :(得分:6)

其他人已经解释了最终化方法。

但请注意,最佳做法是设计一个“关闭”/“清理”/“终止”方法来关闭/清理对象,并要求开发人员明确调用此方法。终结器应仅用作安全网。 (参见Joshua Bloch撰写的“有效Java”的“第7项:避免终结者”)

更新:

在这种情况下,还要考虑实施AutoCloseable以支持try-with-resources块。

答案 2 :(得分:4)

如果您需要手动释放资源(特别是那些使用大量内存或导致锁定的资源,如果它们未被释放),则通常会覆盖finalize方法。例如,如果您有一个对文件或数据库表有锁的对象,您可能希望覆盖finalize方法,以释放这些对象,以便在对象被垃圾回收时使用。

至于是否需要覆盖最终化,绝对不是。您可以在不覆盖finalize方法的情况下调用System.gc()。但需要注意的一点是,调用System.gc()并不能完全决定垃圾收集器会做什么。将其视为对JVM运行垃圾收集的“建议”,而不是“授权”。

答案 3 :(得分:0)

对于非常罕见的情况,实现finalize以释放分配的资源可能是有用的或必要的。最终销毁实例时始终会调用此方法。

如果您使用本机代码并且需要在本机代码区域中释放已分配的资源,则可能会有所帮助。

但要小心使用它,因为实现finally会大大减慢垃圾收集器的速度并导致性能下降。

答案 4 :(得分:0)

1)要对对象销毁进行任何清理(如果你保持一些句柄打开,没有人调用显式关闭)。请记住,您不知道何时会发生这种情况,因为JVM将调用GC而不是您。

2)不。

旁注,您不应手动调用垃圾收集器,请参阅此处的答案,Why do you not explicitly call finalize() or start the garbage collector?

答案 5 :(得分:0)

无法保证会立即调用终结器,因此您不应该在终结方法中做任何关键事情。

  1. 如果系统资源(例如IOStreams)尚未关闭或发布,则将其作为安全网释放。
  2. 发布GC不知道的本机代码中的系统资源。

答案 6 :(得分:0)

@Andreas_D:我同意礁石所说的内容以及他所暗示的是,如果finalize()包含使当前实例不符合GC条件的代码,即通过为活动线程提供对此实例的引用将其恢复生命,然后下次该实例符合GC条件时,不要期望JVM再次调用finalize()。就JVM而言,它已经通过调用finalize()一次完成了它的职责,并且不能再一次又一次地做这件事只是因为你不断地让实例再次恢复生机。如果确实如此,则该对象永远不会被GC化。 (当然,您可能希望实例永远不会被GC。然后只是让一个活动线程维护对它的引用。如果没有活动线程有对该实例的引用,那么该实例就像死了一样好。)

答案 7 :(得分:-1)

  

1.我们在覆盖的finalize()方法中做了什么操作?

清理垃圾收集无法处理的资源。

  

2.如果我们想手动调用JVM垃圾收集器,是否需要覆盖finalize()方法?

不,这两件事是无关的。

finalize肯定不会调用垃圾收集器本身。事实上,finalize被称为 by 垃圾收集器(但不保证完全被调用)。