-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FFITypes for non-base classes are never removed from typeInfoMap
, causing the Cleaner thread to loop forever
#1633
Comments
Could you please provide a minimal reproducer, that shows the problem? |
Yes, for sure! Here is a simple Kotlin program that reproduces the issue:
This program just makes a minimal The struct value Internally, what's going on is that the |
I had to adjust the sample (after translating to java), as the FFIType is only allocated, when the structure is actually allocated. My test case: import com.sun.jna.Structure;
import com.sun.jna.Structure.FieldOrder;
public class JNACollection {
@FieldOrder({"field"})
public static class NativeWrapper extends Structure {
public boolean field = false;
}
private static Thread getCleanerThread() {
for (Thread t : Thread.getAllStackTraces().keySet()) {
if ("JNA Cleaner".equals(t.getName())) {
return t;
}
}
return null;
}
public static void main(String[] artv) throws InterruptedException {
{
NativeWrapper nw = new NativeWrapper();
nw.write();
System.out.println(nw);
}
Thread.sleep(1000);
System.gc();
Thread.sleep(60000);
Thread cleanerThread = getCleanerThread();
System.out.println(cleanerThread);
}
} I see the problem, but I raise the question, how bad this is? This is only one of several hard to close things in JNA, that will keep the cleaner alive. The reason for the existence of the cleaner is, that there is no defined lifecylce for objects tied to native. They are created when needed and are kept alive until their java anchor goes away. I see only a way to fix this by making all objects closeable and use them with try-with-resource, but that has major usage/api impact. |
The
FFIType
class has a staticWeakHashMap
of type information, thetypeInfoMap
. Since it is a weak map, key-value pairs would be removed if the key was garbage collected. However, since the keys in this map are Classes, they are extremely unlikely to ever be collected.For classes that are Structures, the FFIType stored in the
typeInfoMap
wraps the structure object itself, here. However, when the FFIType is a Structure, there is underlyingMemory
in it, which has aMemoryDisposer
registered on it.Since the Class is never unloaded, the FFType cannot be garbage collected either -- however, the Cleaner thread expects to be able to clean up its Memory, and so it will loop forever waiting to be able to clean it.
Potential solutions: I am not sure the best way to go about fixing this problem, but there are two approaches I think of first:
Let me know what you think. I''m trying to hack around this problem right now in my project, and will update this issue when I have a temporary solution too.
The text was updated successfully, but these errors were encountered: