I can give some more concrete pitfalls with finalizers.
* On android, finalize is called on a background thread. Usually chrome objects are owned and destroyed on a specific thread, so delete needs to be posted to another thread.
* On android, finalize timeout after 10 seconds, which crashes the process I believe.
* There is no guaranteed call order when a bunch of objects become finalizable together. So won't work if native objects require a specific destruction order.
* Exceptions are ignored. On android, they print but do not crash, so there is no point in just putting an assert mNativeFoo == 0 in a finalizer, and need something more complex to be useful.
* Should not assume finalize is the last method called on an object. It's allowed to call methods after finalize. This generally isn't a problem for apps, but code that implements a library like content and android webview should assume the worst.
* Finalizers are not chained (unlike constructor). Again, more of a problem for library that has classes that allow client to subclass.
The better alternative to finalizer is using ReferenceQueue, which is what NativeRefAssassin uses. None of the problems above really apply to ReferenceQueue, but it has its own costs.
However neither solves the problem of java-native object ownership. Ownership is complex and difficult to get right, and does not lend itself to be abstracted away with finalizer/ReferenceQueue. I have examples of complexity encountered by webview in
this doc. So I'd say understand your object ownership, and then use explicit destroy if it's needed.