最终确定了4克的大量内存2.5 gig

时间:2016-07-28 11:54:03

标签: java finalizer

我已经阅读了很多关于终结器如何工作的文章。以下是我的理解:如果一个类已经实现了finalize方法,那么Jvm会在该对象上创建一个Finalizer实例作为监视狗。

当GC运行时,它会标记要处置的对象并将它们添加到引用队列中,然后终结器线程将从队列中选择这些对象并执行它们的终结方法。

我的问题是:如何从堆转储中找到对象,其终结方法由于某种原因未完成并开始堆积引用队列?

参考队列是否按特定顺序?

2 个答案:

答案 0 :(得分:0)

这可能不是您正在寻找的答案,但是您是否考虑过使用PhantomReference而不是覆盖finalize()?这是一个谈论它的article

基本思路是不建议依靠finalyze()方法进行预先清理,因为

  • 您无法预测何时会被呼叫。
  • 它占用了JVM的资源。
  • 它可以防止对象被垃圾收集。

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,因此在将对象从内存中删除后,无法将其恢复。

答案 1 :(得分:0)

是的,您可以从堆转储中获取对象。

首先,终结器引用将从java.lang.ref.Finalizer.FinalizerThread#run中的队列中删除,然后在runFinalizer中,它将从方法remove中未终结引用的双向链接列表中删除。

但是你可以找到这个引用,因为你知道GC根(它存在于FinalizerThread'堆栈中)

如何在日食MAT中找到它:

  1. 转到直方图并按类java.lang.ref.Finalizer
  2. 过滤
  3. 右键点击带有终结器的行 - >使用所有引用合并到gc根的最短路径。
  4. 使用FinalizerThread扩展行(通常它应包含一个对象java.lang.Finalizer)
  5. 单击该扩展行,在检查器面板中可以单击属性选项卡,最终对象将是指示对象 enter image description here