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

mch*_*chr 4 java garbage-collection memory-leaks

我在下午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)
  • 会话对象没有可以复活它的终结器,即使它已经完成,它也不能在对象仍处于其他对象后面的未终结队列中时运行.
  • 我的应用程序不使用Phantom引用,它是唯一一个对象有资格完成后应该能够存在的引用.即使我的应用程序确实使用了幻像引用,这些对象也不会公开它们对所持对象的引用.

Cow*_*wan 10

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

Finalizer线程拥有的"未完成"链表的终结器引用.我的目标是排在第3位,最终确定.

如果你在谈论这个:

static private Finalizer unfinalized = null;
Run Code Online (Sandbox Code Playgroud)

在Sun公司Finalizer.java(一个Finalizer包含了nextprev Finalizer,因此"链表"的一部分,对于那些沿在家玩),那么这是不是事情的清单定稿.

Finalizer.add()在完成过程中,当对象无法访问时,调用不是(我认为你是假设的); 相反,该方法在Object的创建时被调用(例如<init>,在本机代码期间,对于任何覆盖的Object finalize().

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

static private ReferenceQueue queue
Run Code Online (Sandbox Code Playgroud)

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

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

希望这可以帮助!