2

当您执行以下操作时,

@Override
protected void finalize() throws Throwable {
    ////////////////////////
    
    this.aVeryBigComponent = null;
    
    ////////////////////////

    super.finalize();
}

声纳抱怨

不好的做法 - 终结器只清空字段

发现错误:FI_FINALIZER_ONLY_NULLS_FIELDS

这个终结器除了空字段外什么都不做。这是完全没有意义的,需要对对象进行垃圾收集、终结,然后再次进行垃圾收集。您应该只删除 finalize 方法。

只要我知道将字段设置为 null 有助于垃圾收集器在第一次运行/生成时销毁对象。如果我不将该字段设置为 null,则该对象可能会被发送到第二代,并且会等待更多时间。

你怎么看?

4

6 回答 6

8

如果我不将该字段设置为 null,则该对象可能会被发送到第二代,并且会等待更多时间。

如果您根本没有终结器那么您的对象将有资格更早地进行垃圾收集,并且其字段不会被计为 GC 根,因此其他对象可能同时有资格进行垃圾收集。

即使您确实需要终结器,除非终结器使对象复活,否则终结的对象仍然有资格进行垃圾回收,因此它的字段不会使其他对象保持活动状态。

用 Java 编写终结器几乎不是一个主意……如果它只是要将字段设置为 null,那绝对是个坏主意。(它几乎肯定会损害性能而不是帮助它。)

于 2013-09-03T11:22:05.597 回答
2

Objects with finalizers (those that have a non-trivial finalize() method) have significant overhead compared to objects without finalizers, and should be used sparingly. Finalizeable objects are both slower to allocate and slower to collect. At allocation time, the JVM must register any finalizeable objects with the garbage collector, and (at least in the HotSpot JVM implementation) finalizeable objects must follow a slower allocation path than most other objects. Similarly, finalizeable objects are slower to collect, too. It takes at least two garbage collection cycles (in the best case) before a finalizeable object can be reclaimed, and the garbage collector has to do extra work to invoke the finalizer. The result is more time spent allocating and collecting objects and more pressure on the garbage collector, because the memory used by unreachable finalizeable objects is retained longer. Combine that with the fact that finalizers are not guaranteed to run in any predictable timeframe, or even at all, and you can see that there are relatively few situations for which finalization is the right tool to use.

If you must use finalizers, there are a few guidelines you can follow that will help contain the damage. Limit the number of finalizeable objects, which will minimize the number of objects that have to incur the allocation and collection costs of finalization. Organize your classes so that finalizeable objects hold no other data, which will minimize the amount of memory tied up in finalizeable objects after they become unreachable, as there can be a long delay before they are actually reclaimed. In particular, beware when extending finalizeable classes from standard libraries.

For complete article please refer to http://www.ibm.com/developerworks/java/library/j-jtp01274/index.html

Hope it helps

于 2013-09-03T11:26:12.543 回答
2

Actaully, it will do the opposite of what you suggest.

I know setting a field to null helps garbage collector destroy an object in the first run/generation.

Using a finalizer means both objects cannot be collected until after the finalizer has been called in the finalization thread.

If I do not set the field to null, that object may be sent to the second generation and will wait more.

If you do not use a finalizer, both objects can be cleaned up at the same time.

于 2013-09-03T11:32:37.193 回答
0

无法保证何时或什至是否调用了终结器。如果一个对象超出范围,它就是 gc 的候选对象。如果它有一个终结器,它将在对象被销毁之前调用。

终结器有可能将对象带回作用域,(它可能会调用一些 register(this) 方法)所以也许这就是垃圾收集器不会在此过程中删除对象的原因,而是等到下一轮来确定是否该对象仍然超出范围。如果它没有终结器,gc 可以确定它没有被带回作用域,因此删除它是安全的。

此外,不要混淆将字段设置为 null 删除对该字段的引用,以及您所在的终结器对象。这是两个独立的对象,可以在不同时间进行垃圾收集。

于 2013-09-03T11:28:16.763 回答
0

声纳是正确的——你不必为 GC 设置对 null 的引用来做正确的事情。

“只要我知道将字段设置为 null 有助于垃圾收集器在第一次运行/生成时销毁对象。” - 据我所知,这些都不重要。GC 比你聪明得多。

于 2013-09-03T11:22:04.333 回答
0

finalize()仅当您的实例即将被垃圾收集时,才会调用您实例上的方法。

这意味着,您的实例的所有字段也将被垃圾收集,因此无需显式这样做。

于 2013-09-03T11:22:38.867 回答