堆转储中不可能的Java内存引用 [英] Impossible Java memory references in Heap Dump

查看:121
本文介绍了堆转储中不可能的Java内存引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



在堆中的这些会话对象之一上使用路径至GC根命令显示以下3个对会话对象的引用。 / p>


  • 来自Finalizer线程拥有的未终止链接列表的终结器引用。我的对象是第三行定稿。

  • 从消息处理程序线程强烈引用会话对象,该线程本身是从计划在晚上7:11运行的清理TimerTask引用的。 / li>
  • 对WeakHashMap $ Entry中的会话对象的弱引用。 WeakHashMap通过静态强引用保持活动状态。



会话对象在仍然有强大的时候如何处于终结器队列中和一个弱引用?



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



几个一般性问题:


  • 对象只有在它们的弱引用已被清除后才有资格进行最终化(http://download.oracle.com/javase/6/docs/api/java/lang/ref/package-summary.html)

  • 会话对象没有可以重新生成的终结器,即使它已经在对象仍然处于其他对象后面的未定义队列中时仍未运行。

  • 我的应用程序不使用Phantom refs,这是唯一一个对象有资格完成时应该能够存在的引用。即使我的应用程序确实使用了phantom refs,这些对象也不会公开对它们所持对象的引用。

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


来自未定界链表的终结器引用由Finalizer线程拥有。我的对象是第三行定稿。


如果您在讨论这个问题:

  static private finalizer unfinalized = null; 

在Sun的 Finalizer.java中(a Finalizer 包含一个下一个 prev Finalizer ,因此是'在家链接'的'链接列表'部分),那么这不是要完成的事情列表。



Finalizer.add()不是(我认为你假设)在最终化过程中调用时,当对象无法访问;相反,该方法在Object的 creation 时间被调用(例如在< init> code> finalize()。



下一个链并不意味着它即将完成;它是

 静态私有ReferenceQueue队列

它持有这样的对象,在链表中意味着它 a finalize()方法。



因此,您的第一点是红鲱鱼,它是保持项目可到达的第二点, (因为 WeakReference 在对象到达时不会被清除)。



希望这有助于!


I have a Java Heap Dump taken at 7:41pm which I am analysing with Eclipse Memory Analysis Tool. The heap dump includes 20 session objects.

Using the Path to GC Roots command on one of these session objects in my heap shows the following 3 references to the session object.

  • A finalizer reference from the "unfinalized" linked list owned by the Finalizer thread. My object is 3rd in line to be finalized.
  • A strong reference to the session object from a message handler thread which is itself referenced from a cleanup TimerTask scheduled to run at 7:11pm.
  • A weak reference to the session object from a WeakHashMap$Entry. The WeakHashMap is kept alive by a static strong reference.

How can the session object be on the finalizer queue when it still has a strong and a weak reference?

Of the remaining 19 session objects, 1 more is in the finalizer queue and has a similar weak reference. All the other 18 session objects are only weakly referenced. Why hasn't the GC cleared these weak refs?

A few general points:

  • Objects are only eligible for finalization AFTER their weak refs have been cleared (http://download.oracle.com/javase/6/docs/api/java/lang/ref/package-summary.html)
  • The session object does not have a finalizer which could resurrect it and even if it did it couldn't have been run while the object is still in the unfinalized queue behind other objects.
  • My application doesn't use Phantom refs which are the only refs which should be able to exist once an object is eligible for finalization. Even if my app did use phantom refs these objects do not expose their reference to the object they hold.

解决方案

I think the mistake you're making here is in this part:

A finalizer reference from the "unfinalized" linked list owned by the Finalizer thread. My object is 3rd in line to be finalized.

If you're talking about this:

static private Finalizer unfinalized = null;

in Sun's Finalizer.java (a Finalizer contains a next and prev Finalizer, hence the 'linked list' part, for those playing along at home), then that's not the list of things to be finalized.

Finalizer.add() is not (as I think you're assuming) called during the finalization process, when the object is unreachable; rather, that method is called at creation time of the Object (e.g. during <init>, by native code, for any Object which overrides finalize().

The presence of a Finalizer in the next chain doesn't mean it's about to be finalized; it's the

static private ReferenceQueue queue

which holds such objects. Being in the linked list just means that it has a finalize() method.

Therefore your first point is a red herring, it's your second point that's keeping the item reachable, and the third point flows from the second (because the WeakReference won't be cleared while the object is reachable).

Hope this helps!

这篇关于堆转储中不可能的Java内存引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆