简体   繁体   English

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

[英]Impossible Java memory references in Heap Dump

I have a Java Heap Dump taken at 7:41pm which I am analysing with Eclipse Memory Analysis Tool. 我在下午7:41进行了Java堆转储,我正在使用Eclipse内存分析工具进行分析。 The heap dump includes 20 session objects. 堆转储包括20个会话对象。

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. 在我的堆中的其中一个会话对象上使用Path to GC Roots命令显示以下3个对会话对象的引用。

  • A finalizer reference from the "unfinalized" linked list owned by the Finalizer thread. Finalizer线程拥有的“未完成”链表的终结器引用。 My object is 3rd in line to be finalized. 我的目标是排在第3位,最终确定。
  • 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. 来自消息处理程序线程的对会话对象的强引用,该消息处理程序线程本身是从计划在晚上7:11运行的清理TimerTask引用的。
  • A weak reference to the session object from a WeakHashMap$Entry. 来自WeakHashMap $ Entry的会话对象的弱引用。 The WeakHashMap is kept alive by a static strong reference. WeakHashMap通过静态强引用保持活动状态。

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. 在剩余的19个会话对象中,还有1个在终结器队列中,并且具有类似的弱引用。 All the other 18 session objects are only weakly referenced. 所有其他18个会话对象仅被弱引用。 Why hasn't the GC cleared these weak refs? 为什么GC没有清除这些弱的参考?

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) 对象只有在他们的弱引用被清除后才有资格完成(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. Finalizer线程拥有的“未完成”链表的终结器引用。 My object is 3rd in line to be finalized. 我的目标是排在第3位,最终确定。

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. 在Sun的Finalizer.java (一个Finalizer包含一个nextprev Finalizer ,因此'链表'部分,对于那些在家里玩的人),那不是最终确定的事情列表。

Finalizer.add() is not (as I think you're assuming) called during the finalization process, when the object is unreachable; Finalizer.add()不是(我认为你假设)在完成过程中调用,当对象无法访问时; rather, that method is called at creation time of the Object (eg during <init> , by native code, for any Object which overrides finalize() . 相反,该方法在Object的创建时被调用(例如,在<init>期间,通过本机代码,对于覆盖finalize()任何Object。

The presence of a Finalizer in the next chain doesn't mean it's about to be finalized; next链中存在终结器并不意味着它即将完成; it's the 是的

static private ReferenceQueue queue

which holds such objects. 它拥有这样的对象。 Being in the linked list just means that it has a finalize() method. 在链表中只是意味着它一个finalize()方法。

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). 因此,您的第一个点是红色鲱鱼,这是您保持项目可达的第二点,第三点从第二点流出(因为WeakReference在对象可达时不会被清除)。

Hope this helps! 希望这可以帮助!

Weak references are only an indication for the GC. 弱参考仅是GC的指示。 You have no hard guarantees when it will be cleared up. 当它被清除时,你没有任何硬性保证。

You can make an object scheduled for finalize available again. 您可以将计划的对象再次设置为可用。

I know about: 我知道:

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. 会话对象没有可以复活它的终结器,即使它已经完成,它也不能在对象仍处于其他对象后面的未终结队列中时运行。

However there might be other objects doing so (ie having ref to the Session and getting themselves rez'd). 然而,可能还有其他对象这样做(即,参与会话并获得自己的rez'd)。 Either way show the finalizer of that Session thingie. 无论哪种方式都显示该Session会议的终结者。

notes: before clearing the phantom refs the Object WILL NOT be available for finalization. 注意:在清除幻像之前,对象将不可用于最终确定。 (Phantom references are most often used for scheduling pre-mortem cleanup actions, javadoc ), pre (not post like Weak ones). (幻像引用最常用于安排预先清理操作, javadoc ),pre(不像弱者那样发布)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM