我已经阅读了许多文章如何终结者的作品。这里是我的理解:如果一个类已经实现了finalize方法,那么Jvm将创建一个Finalizer实例作为该对象的监视器。最终确定是持有大量的内存2.5 gig 4 g
当GC运行时,它会标记要放置的对象并将它们添加到引用队列中,然后终结器线程将从队列中选择这些对象并执行它们的finalize方法。
我的问题是:如何从堆转储找到对象,其中的finalize方法由于某种原因未完成,并开始堆积参考队列?
是否按特定顺序引用队列?
我已经阅读了许多文章如何终结者的作品。这里是我的理解:如果一个类已经实现了finalize方法,那么Jvm将创建一个Finalizer实例作为该对象的监视器。最终确定是持有大量的内存2.5 gig 4 g
当GC运行时,它会标记要放置的对象并将它们添加到引用队列中,然后终结器线程将从队列中选择这些对象并执行它们的finalize方法。
我的问题是:如何从堆转储找到对象,其中的finalize方法由于某种原因未完成,并开始堆积参考队列?
是否按特定顺序引用队列?
这可能不是您正在寻找的答案,但您是否考虑过使用PhantomReference
而不是覆盖finalize()
?这是一个谈论它的article。
的基本思路是,不建议依靠finalyze()
方法的验前的清理,因为
PhantomReference
提供了一种更简洁的方式来触发垃圾收集器清除对象时的操作。
Object objectToHandle = new Object();
ReferenceQueue queue = new ReferenceQueue();
PhantomReference reference = new PhantomReference(objectToHandle, queue);
objectToHandle
时将从存储器通过垃圾收集器被移除,其reference
将被添加到所述queue
。您可以通过拨打queue.remove()
来检测,然后执行清理操作。
// will block until a reference becomes available
Reference removedRef = queue.remove();
//.. you can now perform clean-up actions
注:PhantomReference.get()
总是返回null
,所以不可能之后已经从内存中删除带回的对象。
是的,您可以从堆转储中获取对象。
首先,终结符ref将从java.lang.ref.Finalizer.FinalizerThread#run
的队列中移除,然后在runFinalizer
中,将从方法remove
中的未连接的ref的双向链表中删除。
但是你可以找到这个裁判,因为你知道它GC根(它存在于FinalizerThread堆栈)
如何找到它在Eclipse MAT:由级Java
感谢您的回复。我没有看到检查员小组的选择。我如何打开检查员面板。 –
没关系。非常感谢你的帮助。我能找到选项。 –
只是想知道:什么是你的终结方法在做什么?为什么你有那么多想要使用方法的对象,至少在理论上,没有人应该依赖? – GhostCat
从源代码看来,ReferenceQueue的工作方式与List类似 - 它包含Reference对象,每个Reference引用下一个Reference。也许第一个对象是你需要的。 也许你应该尝试在finalize方法上添加方面并添加一些日志记录(例如调用Finalize for xxx;完成完成) - 行中的最后一项将指向已开始完成的对象,但最终确定并未完成。 – ekaerovets
我可能会用另一种方式去执行一个文本搜索,这些类有'finalize()'的非平凡实现 - 你的代码库中有太多候选人吗? – Hulk