堆转储中不可能的Java内存引用

时间:2011-01-13 12:36:16

标签: java memory-leaks garbage-collection

我在晚上7:41进行了Java堆转储,我正在使用Eclipse内存分析工具进行分析。堆转储包括20个会话对象。

在我的堆中的其中一个会话对象上使用Path to GC Roots命令显示以下3个对会话对象的引用。

  • Finalizer线程拥有的“未完成”链接列表的终结器引用。我的目标是排在第3位。
  • 来自消息处理程序线程的会话对象的强引用,该线程本身是从计划在晚上7:11运行的清理TimerTask引用的。
  • 来自WeakHashMap $ Entry的会话对象的弱引用。 WeakHashMap通过静态强引用保持活动状态。

当会话对象仍然具有强引用和弱引用时,它如何在终结器队列上?

在剩余的19个会话对象中,还有1个在终结器队列中,并且具有类似的弱引用。所有其他18个会话对象仅被弱引用。为什么GC没有清除这些弱的参考?

一些要点:

  • 对象只有在他们的弱引用被清除后才有资格完成(http://download.oracle.com/javase/6/docs/api/java/lang/ref/package-summary.html)
  • 会话对象没有可以复活它的终结器,即使它已经完成,但是当对象仍在其他对象后面的未终结队列中时,它无法运行。
  • 我的应用程序不使用幻影引用,这是唯一一个对象有资格完成后应该能够存在的引用。即使我的应用程序确实使用了幻像引用,这些对象也不会公开它们对所持对象的引用。

3 个答案:

答案 0 :(得分:10)

我认为你在这里犯的错误就是这个部分:

  

Finalizer线程拥有的“未完成”链接列表的终结器引用。我的目标是排在第3位。

如果你在谈论这个:

static private Finalizer unfinalized = null;

在Sun的Finalizer.javaFinalizer包含nextprev Finalizer,因此是“链接列表”部分,适用于在家中玩的人),那不是最终确定的事项清单。

在完成过程中,当对象无法访问时,

Finalizer.add()不是(我认为你在假设)。相反,该方法在对象的创建时间调用(例如在<init>期间,由本机代码调用,用于覆盖finalize()的任何对象。

next链中存在终结器并不意味着它即将完成;

static private ReferenceQueue queue

持有这样的对象。在链表中只是意味着它 一个finalize()方法。

因此,你的第一点是红鲱鱼,这是你的第二点保持物品可达,第三点从第二点流出(因为在物体可到达时不会清除WeakReference)。

希望这有帮助!

答案 1 :(得分:0)

弱参考仅是GC的指示。当它被清除时,你没有任何硬性保证。

答案 2 :(得分:0)

您可以再次安排最终确定的对象。

我知道:

  

会话对象   没有终结者可以   复活它,即使它做到了   不能跑的时候   对象仍处于未完成状态   在其他对象后面排队。

然而,可能有其他对象这样做(即已经参加会议并获得自己的rez'd)。无论哪种方式都显示该会话的终结者。

注意:在清除幻像之前,对象将无法完成。 (幻像引用最常用于安排预先验证清除操作, javadoc ),pre(不像弱文章那样发布)。