【问题标题】:Finalized is holding lot of memory 2.5 gig out of 4 gFinalized 持有大量内存 2.5 gig out of 4 g
【发布时间】:2016-07-28 11:54:03
【问题描述】:

我已经阅读了很多关于终结器如何工作的文章。这是我的理解:如果一个类实现了 finalize 方法,Jvm 将创建一个 Finalizer 实例作为该对象的看门狗。

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

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

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

【问题讨论】:

  • 只是想知道:你的终结器方法在做什么?为什么你有这么多对象想要使用一种方法,至少在理论上,没有人应该依赖?
  • 从源代码看来,ReferenceQueue 就像一个 List 一样工作——它包含 Reference 对象,每个 Reference 都指向下一个 Reference。也许第一个对象就是你需要的。也许您应该尝试在 finalize 方法上添加方面并添加一些日志记录(例如为 xxx 调用 Finalize;Finalize 已完成) - 行中的最后一个条目将指向已开始完成但 finalize 未完成的对象。
  • 我可能会另辟蹊径,对具有 finalize() 的非平凡实现的类执行文本搜索 - 您的代码库中是否有太多候选对象?
  • @Hulk GC 不运行终结器。请参阅java.lang.ref.Reference 类和嵌套的ReferenceHandler 类。 GC 只添加对静态字段pending 的引用。所有其他工作都在 Reference Handler 和 Finalizer 线程中的 java 代码中完成
  • @commit-man 公平点。删除了不正确的评论。我想我把它弄混了,因为我刚刚阅读了finalize 中的措辞:“当垃圾收集器确定不再有对该对象的引用时,由垃圾收集器在对象上调用。”

标签: java finalizer


【解决方案1】:

这可能不是您要寻找的答案,但您是否考虑过使用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,所以在对象已经从内存中删除后,不可能再将其取回。

【讨论】:

    【解决方案2】:

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

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

    但是你可以找到这个 ref,因为你知道它是 GC root (它存在于 FinalizerThread 的堆栈中)

    如何在eclipse MAT中找到它:

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

    【讨论】:

    • 感谢您的回复。我没有看到检查员面板的选项。如何打开检查器面板。
    • 没关系。非常感谢你的帮助。我能够找到该选项。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-21
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多