是否应该选择Java 9清洁器作为最后定稿的首选?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (117)

在Java中,覆盖该finalize方法会得到一个糟糕的说唱,虽然我不明白为什么。类似于FileInputStream使用它来确保close在Java 8和Java 10中调用。然而,引入的Java 9 java.lang.ref.Cleaner使用PhantomReference机制而不是GC终结。起初,我认为这只是向第三方类添加定稿的一种方式。但是,其javadoc中给出的示例显示了一个可以使用终结器轻松重写的用例。

我应该finalize用Cleaner 重写我的所有方法吗?(当然,我没有很多。只是一些使用OS资源的类,特别是对于CUDA互操作。)

据我所知,Cleaner(通过PhantomReference)避免了一些危险finalizer。特别是,您无法访问已清理的对象,因此无法复原它或其任何字段。

然而,这是我能看到的唯一优势。清洁工也非常重要。事实上,它和终结都使用了ReferenceQueue!(难道你不喜欢阅读JDK是多么容易吗?)它比完成更快吗?它是否避免等待两个GC?如果许多对象排队等待清理,它会避免堆耗尽吗?(所有这些的答案在我看来都不是。)

最后,实际上没有任何保证阻止您在清理操作中引用目标对象。小心阅读长API注意!如果你最终引用了对象,那么整个机制将会无声地中断,这与总是试图跛行的终结不同。最后,虽然终结线程由JVM管理,但创建和保存Cleaner线程是您自己的责任。

提问于
用户回答回答于

正如Elliott在评论中指出的那样,继续使用Java9 +,Object.finalize它已被弃用,因此使用它实现方法更有意义Cleaner。另外,从发行说明:

java.lang.Object.finalize方法已被弃用。最终确定机制本质上存在问题,可能导致性能问题,死锁和挂起。在java.lang.ref.Cleanerjava.lang.ref.PhantomReference提供更灵活和有效的方式来释放资源,当一个物体变得无法访问。

Bug数据库中的详细信息 - JDK-8165641

用户回答回答于

Java 9的Cleaner非常类似于传统的终结(在OpenJDK中实现),几乎关于最终化的所有(好的或坏的)可以说是关于Cleaner。两者都依赖垃圾收集器将Reference对象放在a上ReferenceQueue并使用单独的线程来运行清理方法。

三个主要区别是Cleaner使用PhantomReference而不是本质上是a WeakReference,使用每个Cleaner的单独线程和可自定义的ThreadFactory,并允许手动清除(即取消)PhantomReferences并且从不排队。

当大量使用清洁剂/定型时,这提供了性能优势。(不幸的是,我没有基准来说明有多大的优势。)然而,大量使用终结并不正常。

对于finalize常用的东西- 即,本机资源的最后一次清理机制是用小的,最终的对象实现的,这些对象保持最小的必要状态,提供AutoCloseable,而不是每秒分配数百万 - 这里有除了finalize更容易实现之外,两种方法之间没有实际区别。清洁工不提供任何额外的保证或行为(例如保证清洁工将在退出流程之前运行 - 这基本上无法保证)。

但是,finalize已被弃用。就是这样,我想。一种鸡巴动作。也许JDK开发人员在想,“为什么JDK应该提供一个可以轻松实现为库的本机机制。” 这是一个好点 - 然而,我无法想象finalize实际上正在消失。它可能总是有效,所以我不会停止使用它。

Cleaner不闪耀的是一个很好的,内置的实施PhantomReferences格局。所以如果你曾经想过,“哎呀,我需要用PhantomReferences”,那么Cleaner就是你的朋友。然而......通常的论点再次finalizers适用,所以你最好三思而后行。

一篇很好的文章讨论了最终化并概述了替代定型如何工作可以在这里找到:如何处理Java Finalization的内存保留问题它大致描绘了Cleaner的工作原理。

扫码关注云+社区

领取腾讯云代金券