由于几乎没有什么保证关于什么时候甚至终结器运行和终结器现在几乎被认为是气味 - 有没有办法说服JVM完全跳过所有的终结过程?
我问,因为我们有一个庞大的应用程序,当移动到更新的JVM(不确定在这个阶段)是什么看起来非常类似于终结器的已知问题(异常被抛出,因此非常慢GC)。
加
对Troubleshooting a java memory leak: finalization?进行了一些讨论,建议在终结器中抛出异常时会出现主要问题,因为这会大大减慢终结过程。
我的问题显示,当内存变低且堆转储的分析显示大量Finalizer
个对象(超过10,000,000)时显着减速 - 向我建议减速可能是他们的错,因为他们是延迟GC。显然我可能错了。
我没有权力要求重构。
答案 0 :(得分:6)
有没有办法说服JVM完全跳过所有的终结过程?
单词No。
但除非你的大部分对象都有finalize
个方法和/或finalize
方法特别昂贵,否则我认为它们不太可能使GC“非常慢”。我希望问题是别的。
我建议您打开GC日志记录,尝试更好地了解实际情况。
但我也同意,从长远来看,重构代码以摆脱finalize()
方法可能是一件好事。 (极少数情况下使用finalize
确实是最佳解决方案。)
更新 - 您的新证据非常有说服力,但不是证明!
我没有权力要求重构。
然后,我建议你把证据放在那些人的脚下: - )。
或者,您可以向可疑finalize
方法添加异常处理程序,以查看它们是否 抛出异常。 (如果它们是,那么改变它们以避免抛出异常......)
但最重要的是,如果最终确定是导致性能问题的真正原因,那么最好(也可能是唯一)解决这些问题的方法就是更改代码。
答案 1 :(得分:2)
可以抑制某些对象的终结。正如一位评论者指出的那样,不需要字节码操作。
描述了该过程here并提供了源代码。类java.lang.ref.Finalizer
负责维护尚未最终确定的对象列表。要禁止最终确定您感兴趣的对象,只需使用反射API获取字段lock
上的锁定,迭代Finalizer类维护的链接列表unfinalized
,并从中删除您的对象列表。
我已经尝试过这种方法来安全地实例化自定义序列化对象,同时绕过构造函数调用,并避免在使用普通GC调用终结器时出现问题。在应用此方法之前,我的JVM会破坏终结器线程中的硬错误;因为应用这种方法不会发生故障。
答案 2 :(得分:0)
你无法在java中关闭finalizer
,但你所能做的就是编写有助于GC的代码: - )。