在 Java9 中,终结器已被弃用,取而代之的是引入了清理器。两者有什么区别?

In Java9, finalizers have been deprecated, instead cleaners have been introduced. What is the difference between the two?

在 Java9 中,终结器已被弃用,并引入了清洁器的新概念。具体原因是什么?是否有任何特定的场景或原因应该优先使用清洁器而不是终结器(假设建议使用 none)。?

寄存器中的Deprecation of Finalizer说明了决定的原因:-

Finalizers are inherently problematic and their use can lead to performance issues, deadlocks, hangs, and other problematic behavior.

Furthermore, the timing of finalization is unpredictable with no guarantee that a finalizer will be called. Classes whose instances hold non-heap resources should provide a method to enable explicit release of those resources, and they should also implement java.lang.AutoCloseable if appropriate.

proposed solution as an alternative to using the Finalizers were the introduced Cleaners 可以轻松注册和取消对象的清理功能。

The Cleaner and PhantomReference provide more flexible and efficient ways to release resources when an object becomes unreachable.

应用程序创建一个清理服务供自己使用,并且该服务在不再使用时终止。

使用:一旦一个物体变成幻影reachable the cleanup actions performed on the same are registered and managed by a Cleaner. Registering an object reference and corresponding cleaning action returns a Cleanable。最有效的用法是在对象关闭或不再需要时显式调用 clean 方法。

:在Java9之前,Cleaner的类似实现也已经residing under sun.misc package .

我真的建议尽量不要使用终结器或清理器。改用 class AutoCloseable 并在 close() 方法中进行任何清理。

Cleaners 是一种尝试,使终结器像例程一样不易受到终结器攻击。但是 Cleaners 很难正确书写。

什么是终结器攻击?
Finalizer 是 运行,即使一个对象没有完全构造(比如它在构造函数中抛出异常)攻击者可以 subclass 你的漏洞 class 并覆盖它 finalize 方法可能会绕过构造函数内部进行的安全或不变检查。

所以为什么要使用清洁剂。

  1. 不会污染 class 的 public API(因为 Cleaners 和相关对象是私有的)
  2. 不需要创建一个空的 final finalize 方法,即使您不需要它来防止 subclasses 作为攻击的一部分覆盖它.
  3. 防止终结器攻击。
  4. 清洁剂仅 运行 一次

编辑:经过深思熟虑,我意识到清理器并不能阻止终结器攻击。所以即使你在非finalclass中使用cleaner,也请做一个空的finalfinalize方法。