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](https://docs.oracle.com/javase/9/docs/api/java/lang/ref/Cleaner.html) 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.