It is currently possible to resurrect finalizable objects or even phantom references after they have been finalized:
- Create JNI weak reference to object
- Create phantom reference to object/ use object with finalize() method, so that a FinalReference is created.
As soon as the object is no longer strongly reachable, the Finalizer will invoke finalize() on the object, or, if it has been wrapped in a PhantomReference, that PR will be enqueued in its ReferenceQueue. With some luck, it is still possible to get hold of the original object via the JNI weak reference.
This is actually specified in JNI specification:
https://docs.oracle.com/en/java/javase/11/docs/specs/jni/functions.html#weak-global-references
"The weak global reference is weaker than other types of weak references (Java objects of the SoftReference or WeakReference classes). A weak global reference to a specific object will not become functionally equivalent to NULL until after SoftReference or WeakReference objects referring to that same specific object have had their references cleared.
The weak global reference is weaker than Java's internal references to objects requiring finalization. A weak global reference will not become functionally equivalent to NULL until after the completion of the finalizer for the referenced object, if present.
Interactions between weak global references and PhantomReferences are undefined. In particular, implementations of a Java VM may (or may not) process weak global references after PhantomReferences, and it may (or may not) be possible to use weak global references to hold on to objects which are also referred to by PhantomReference objects."
The implementation in referenceProcessor.cpp even has a comment about it:
// Weak global JNI references. It would make more sense (semantically) to
// traverse these simultaneously with the regular weak references above, but
// that is not how the JDK1.2 specification is. See #4126360. Native code can
// thus use JNI weak references to circumvent the phantom references and
// resurrect a "post-mortem" object.
(Notice: I don't have access to bug#4126360, I cannot tell if there is any interesting discussion about the usefulness there.)
However, it turns out that the above clarification to JNI weak reference specification has been removed since Java 13:
https://docs.oracle.com/en/java/javase/13/docs/specs/jni/functions.html#weak-global-references
Which means that we are, strictly speaking, now free to rectify the situation. And since this 'feature' doesn't seem to have any useful applications, and only serves to shoot oneself into its own foot, I propose that we go ahead and do that.