We're seeing a weird AddressSanitizer (clang/C++) "heap-use-after-free" violation that might relate to a finalizer corner case.
Let's say, a Java object OBJ has a handle to to a native resource X. A thread that created OBJ before, is now making a call on OBJ.method(), which calls into a (static) native method staticMethod(X), in which X is used.
Now, at more or less the same time, we're seeing a thread deleting the native resource X. We strongly assume that this triggered by the finalizer calling OBJ.finalize(), which does "delete X".
Is this a valid thing to do for a finalizer?
(OpenJDK 8)
A safe way to do this seems to be using non-static native JNI methods.
In C/C++, a static JNI method signature looks something like this:
Note the second parameter
jclass type
passing the JNI representation of a Java class.A non-static JNI method, however, accepts the current Java instance object (
this
) instead and looks like this:Background: The VM seems to optimize garbage collection quite aggressively. A thread still running a (non-static) method but calling only into a native static method does NOT prevent the object from being freed. If the JNI method is non-static however, this tells the VM that the Java object is still being referenced. Then, only once the the call returns this native reference to the object is cleared. Thus, no finalizer is allowed to run before that.
Default implementation of
finalize()
method does nothing:Your description sounds like shared native resource was removed in one thread while it is required in another thread. You need to check out all native methods (in java) which removes something from native memory space.
Java don't know about objects allocated in native code. You need manually control this via native calls. For example: