应该优先使用Java 9 Cleaner而不是定稿吗? [英] Should Java 9 Cleaner be preferred to finalization?

查看:120
本文介绍了应该优先使用Java 9 Cleaner而不是定稿吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中,重载finalize方法会带来糟糕的说唱声,尽管我不明白为什么.诸如FileInputStream之类的类使用它来确保在Java 8和Java 10中都调用close.但是,Java 9引入了java.lang.ref.Cleaner,它使用PhantomReference机制而不是GC终结.起初,我认为这只是将终结处理添加到第三方类中的一种方法.但是,其javadoc 显示了一个用终结器可以轻松重写的用例.

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

正如我所知,Cleaner(通过PhantomReference)避免了finalizer的某些危险.特别是,您无权访问已清除的对象,因此无法恢复该对象或其任何字段.

但是,这是我所能看到的唯一优势.清洁也很重要.实际上,它和终结处理都使用ReferenceQueue! (您不只是喜欢阅读JDK多么容易吗?)它比定稿要快吗?是否避免等待两个GC?如果有许多对象排队进行清理,它将避免堆耗尽吗? (所有这些答案在我看来都是否".)

最后,实际上并不能保证阻止您在清理操作中引用目标对象.请仔细阅读较长的API注意!如果最终引用该对象,则整个机制将无声地中断,这与完成过程总是试图li行的终结不同.最后,虽然终结处理线程是由JVM管理的,但是创建和保留Cleaner线程是您自己的责任.

解决方案

两者都不使用.

使用Cleaner尝试从资源泄漏中恢复所带来的挑战几乎与finalize一样多,如Holger所言,最坏的挑战是过早的终结(这不仅是finalize的问题,而且还存在每种问题软/弱/幻像参考).即使您尽最大努力正确地实现了终结处理(再一次,我的意思是任何使用软/弱/幻象引用的系统),您都无法保证资源泄漏不会导致资源耗尽.不可避免的事实是GC不了解您的资源.

相反,您应该假设资源将被正确关闭,发现并修复错误,而不是希望解决这些错误,并且仅将finalization(以任何形式使用)用于调试. >

必须修复资源泄漏-不能解决.

为此,我建议看看Netty派生的 almson-refcount .它基于弱引用提供了有效的资源泄漏检测器,并且提供了一个可选的引用计数工具,该工具比通常的AutoCloseable更加灵活.使其泄漏检测器出色的原因在于它提供了不同级别的跟踪(具有不同的开销),并且您可以使用它来捕获堆栈跟踪,以了解泄漏对象的分配和使用位置.

In Java, overriding the finalize method gets a bad rap, although I don't understand why. Classes like FileInputStream use it to ensure close gets called, in both Java 8 and Java 10. Nevertheless, Java 9 introduced java.lang.ref.Cleaner which uses the PhantomReference mechanism instead of GC finalization. At first, I thought it was just a way add finalization to third-party classes. However, the example given in its javadoc shows a use-case that can easily be rewritten with a finalizer.

Should I be rewriting all of my finalize methods in terms of Cleaner? (I don't have many, of course. Just some classes that use OS resources particularly for CUDA interop.)

As I can tell, Cleaner (via PhantomReference) avoids some of the dangers of finalizer. In particular, you don't have any access to the cleaned object and so you can't resurrect it or any of its fields.

However, that is the only advantage I can see. Cleaner is also non-trivial. In fact, it and finalization both use a ReferenceQueue! (Don't you just love how easy it is to read the JDK?) Is it faster than finalization? Does it avoid waiting for two GCs? Will it avoid heap exhaustion if many objects are queued for cleanup? (The answer to all of those would appear to me to be no.)

Finally, there's actually nothing guaranteeing to stop you from referencing the target object in the cleaning action. Be careful to read the long API Note! If you do end up referencing the object, the whole mechanism will silently break, unlike finalization which always tries to limp along. Finally, while the finalization thread is managed by the JVM, creating and holding Cleaner threads is your own responsibility.

解决方案

Use neither.

Trying to recover from resource leaks using Cleaner presents nearly as many challenges as finalize the worst of which, as mentioned by Holger, is premature finalization (which is a problem not only with finalize but with every kind of soft/weak/phantom reference). Even if you do your best to implement finalization correctly (and, again, I mean any kind of system that uses a soft/weak/phantom reference), you can never guarantee that the resource leaks won't lead to resource exhaustion. The unavoidable fact is that the GC doesn't know about your resources.

Instead, you should assume that resources will be closed correctly, find and fix bugs rather than hope to work around them, and use finalization (in any of its forms) only for debugging.

Resource leaks must be fixed--not worked around.

To that end, I suggest taking a look at the Netty-derived almson-refcount. It offers an efficient resource leak detector based on weak references, and an optional reference-counting facility that is more flexible than the usual AutoCloseable. What makes its leak detector great is that it offers different levels of tracking (with different amounts of overhead) and you can use it to capture stack traces of where your leaked objects are allocated and used.

这篇关于应该优先使用Java 9 Cleaner而不是定稿吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆