Java不使用finalize()覆盖释放对象

时间:2014-03-13 13:05:50

标签: java garbage-collection finalizer

我的应用程序使用第三方库(JTDS驱动程序),它有一些覆盖finalize()方法的对象。我认为他们遵守所有关于何时不使用finalize()的规则 - 它并不依赖于它们及时运行或根本不运行。

问题是他们的对象永远不会被释放。它们似乎陷入了Finalizer队列并且从未被删除过。它们在几周内缓慢积累并从堆空间中运行JVM。线程转储显示Finalizer线程正在等待调用finalize()的内容。如果我调用System.runFinalization(),对象将被最终确定并从终结器队列中正确删除(并且不再显示在堆转储中)。

为什么System.runFinalization()会正确删除对象,但Finalizer线程不会单独执行此操作?

3 个答案:

答案 0 :(得分:1)

今天有同样的问题。你没有指定你正在使用的JVM,只是它是OpenJDK - 有一个bug https://lists.launchpad.net/openjdk/msg10021.html 他们说它已经修复,所以你只需要升级。

答案 1 :(得分:0)

这意味着你的finalize()方法花费的时间太长,导致队列中的对象等待被调用。

对象在被调用时从队列中删除,并在被调用后不会进入队列。

答案 2 :(得分:0)

  

为什么Finalizer线程不会删除这些对象?

简单的答案是,终结器的某些方面导致了死锁。终结者是最糟糕的清理方式。它由垃圾收集器调用。

  

垃圾收集时由垃圾收集器调用对象   确定没有对该对象的更多引用。   当要作为垃圾收集器的对象具有强引用时会发生什么?该对象永远不会被垃圾收集器。我强烈怀疑这是你的情况。

Joshua Bloch在Effective Java中说:

  

总之,除了作为安全网或终止之外,不要使用终结器   非关键的原生资源

避免终结者 - 终结者是不可预测的,通常是危险的,而且通常是不必要的

http://www.informit.com/articles/article.aspx?p=1216151&seqNum=7