在Java9中,终结器(finalizers)已经被弃用,引入了清理器(cleaners)的新概念。这个具体原因是什么?是否有任何特定场景或原因可以优先考虑使用清理器而不是终结器(尽管它们都不被推荐)?
在Java9中,终结器(finalizers)已经被弃用,引入了清理器(cleaners)的新概念。这个具体原因是什么?是否有任何特定场景或原因可以优先考虑使用清理器而不是终结器(尽管它们都不被推荐)?
Finalizer存在问题,使用可能导致性能问题、死锁、挂起和其他问题。
此外,终结时间不可预测,不能保证一定会调用终结器。持有非堆资源实例的类应提供一种方法来显式释放这些资源,并且如果适当,则应实现
java.lang.AutoCloseable
。
作为Finalizer替代方案的Cleaners可以提供对象清理函数的简单注册和取消。
Cleaner
和PhantomReference
提供了更加灵活高效的方式,在对象变得不可访问时释放资源。
应用程序可创建自己的清理服务,并在不再使用时终止该服务。
使用方法:一旦对象已成为虚引用可达,则对同一对象的清理操作由Cleaner注册并管理。将对象引用和相应的清理操作注册后,将返回一个Cleanable
对象。最有效的使用方式是在关闭对象或不再需要时显式调用clean
方法。
注意:在Java9之前,一个类似的Cleaner实现也存在于sun.misc
包下。详情请参考此处。
finalize()
方法污染我的代码。只有在以下3种情况下才与您有关:1)您的代码真正与安全性相关,2)您允许不受信任的代码对您的类进行子类化 并且 3)在验证参数之前,您的构造函数使对象处于可利用状态。如果您在分配资源之前验证参数,攻击者的finalize()
方法将只看到null
引用。如果在调用超类构造函数之前拒绝无效参数,则根本没有最终处理。 - Holger