我的应用程序使用第三方库(JTDS驱动程序),它有一些覆盖finalize()方法的对象。我认为他们遵守所有关于何时不使用finalize()
的规则 - 它并不依赖于它们及时运行或根本不运行。
问题是他们的对象永远不会被释放。它们似乎陷入了Finalizer队列并且从未被删除过。它们在几周内缓慢积累并从堆空间中运行JVM。线程转储显示Finalizer线程正在等待调用finalize()
的内容。如果我调用System.runFinalization()
,对象将被最终确定并从终结器队列中正确删除(并且不再显示在堆转储中)。
为什么System.runFinalization()
会正确删除对象,但Finalizer线程不会单独执行此操作?
答案 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