【问题标题】:Prevent Java VM from finalizing an object阻止 Java VM 完成对象
【发布时间】:2016-08-14 20:30:57
【问题描述】:

有没有办法告诉 Java VM(在本例中是 HotSpot 或 Zing)不再将对象视为存在 finalize 方法?真的,如果可能的话,我猜是全班同学。

我遇到了一些对象的问题,这些对象已经释放了资源,但仍然对认为需要对其调用 finalize 的 VM 施加了压力。

这是在库中,所以无法更改类。

用例是一个库,如果您忘记或决定让 GC 为您清理堆外资源。问题是我有很多人在附近闲逛。

【问题讨论】:

    标签: java jvm finalize azul-zulu


    【解决方案1】:

    您唯一的选择是使用一个代理 (-javaagent),它将用一个空的代理覆盖 finalize 实现。 JVM 自动为具有非空 finalize 的类的每个实例创建一个 FinalReference 对象(这就是 JVM (Oracle) 跟踪可终结对象的方式)。你无法改变他的行为。

    【讨论】:

    • 我一直在考虑这一点:一个自定义加载器在加载时删除了 finalize 方法,但我真的不想深入了解它。我从来没有使用过代理的东西,只是重写了一些字节码,我认为我可以为这个特定的应用程序在更高级别上破解它。
    【解决方案2】:

    用例是一个库,如果您忘记或决定让 GC 为您清理堆外资源。

    为此,我们使用Cleaner,就像ByteBuffer 一样。这是一种更轻量级的资源清理方式。


    编辑另一个选择是你可以

    • 获取Finalizer.queue 并在持有Finalizer.lock 的同时自行删除元素您可以添加一个线程,定期清理不需要存在的元素队列。
    • 您可以用您自己的实现替换此队列,使其行为不同。例如首先不要添加所选类的对象。

    【讨论】:

    • 其中有一个,但也有一个 finalize() 方法,它基本上做同样的事情。在这种情况下,清洁器将其回收到对象池中。 (仅供参考,这是 Tibrv 吸吮和我们正在使用的另一个库的组合 - 我有第二个库的 src,但改变它很丑)。
    • @JasonN 理论上,标头记录了一个对象是否已经调用了 finalize() 并防止它被第二次调用。您可以尝试过早地设置它。
    • 这实际上是一个有趣的想法。我想知道它是否会消除 GC 问题,或者我最终还是会有 50 万个对象等待被跳过。
    • 经过一番思考,我认为使用 finalize 标志可能行不通。无论如何,它仍然会出现在两次 GC 通行证的终结器列表中。如果对象复活,这只是防止 Java 调用 finalize()
    • @JasonN 我原以为这会阻止它首先被添加到队列中。
    【解决方案3】:

    不,你不能这样做。它是 JVM 规范的一部分。也不清楚为什么要这样做; VM 将在清理时调用finalize(),如果他们有该方法,则不管之前发生了什么。如果您直接调用 finalize 并触发某种双重 finalize 错误,那么答案很简单:“不要那样做”

    【讨论】:

    • 用例是一个库,如果您忘记或决定让 GC 为您清理堆外资源。这不是错误,但没有 VM 可以很好地处理 finalize 或 WeakRefs,而且我的 VM 有 500k 的它们。一般的策略是永远不要使用它们。永远,当延迟很重要时。由于这是一个图书馆,我无法关闭它。也许我可以在加载时对类文件进行一些猴子修补,但我希望有一个更简单的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多