-
Notifications
You must be signed in to change notification settings - Fork 1
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
Memory leak on HeavyCallMeFromJava Unit Test #3
Comments
@pavelsavara this is what I've got so far Unfortunately I haven't managed yet to check native java scenario yet, because of #10 |
It seems |
Thank you. I created a PhantomReference mechanism inside Object and Exception classes in java and a background thread to run the DisposeClrHandle() cleanup code. This seems to (almost) fix the memory leak on the java side, however uncovered the fact the reference is hold by CLR and waits JNI to release it. Because of this the DisposeClrHandle() does not run, so there is memory leak in the CLR side too, since at the end of the day no-one calls IntHandle.Free() for the JVMProxy It begins to look like cyclic reference between CLR and JVM in this scenario. I will try to understand better these proxy dependencies and create a pull request with a fix at some point, however I think that this mess shouldn't happen in normal circumstances. |
I'm not so sure. Our best outcome would be to at least have API which allows to dispose things manually (or break cycle). Usual problematic pattern is to register some UI event callback an forget about it, never un-register. |
Yes something like .forceDispose() in the base object to release the proxy on the other side seems nice. Is this what you had in mind? Now for this particular issue I faced, I reached a point now that although Object gets garbage collected, the GC does not add the reference to the ReferenceQueue<> thus I loose track of it to call the cleanupcode. I thought that maybe this is some peculiarity since the Object was created through JNI Today I will also try the following which is supported by Java 9 and later
|
possibly |
Maybe it's just me and my weirdness :), but I wouldn't extend IDisposable, because this would imply that the Object should get disposed otherwise it will leak resources. In such case I would use some other more explicit method for enforcing dispose. But I do not insist, it's just semiology. Now with this memory leak, it's still a headache, I have been a few hours on this. But I will figure this out. I used the Cleaner and JVM GC behaves like it refuses to collect the cleaner phantom references to Object for some obscure reason. Now they pile up like the finalizers did before. My first thought it that they are kept by the JNI mechanism, this is why I brought up the cyclic reference issue. But I am not sure yet. At least now, the cleanup code runs and Objects are released from the CLR side. |
I don't insist either. Feel free to make it separate interface.
I think that JVM spec has no guarantees on when finalizers would be run, it at all. So maybe that's that. Also there are few types of GC that JVM implements. And they are configurable. I think we should aim at something which works everywhere. I'm sharing this because it could help you to debug why GC did or didn't run. https://www.baeldung.com/java-verbose-gc
🎉 |
The crazy thing is that the Cleaner code runs, which according to documentation this suggests that the garbage collector has indeed run, found that there are no more live references to that object, and it is eligible for garbage collection. I double checked that there are no other references to Object apart from the cleaner phantom references. Noone touches the Object during cleaning. I even created a second thread to monitor the clrHandles and call CLR side cleaning from there to make sure that Object gets cleaned without touching JNI directly. I will revisit the issue after closing #10 to study how this behaves when the process starts from Java, to make sure that it's not some peculiarity due to back and forth between runtimes through JNI. |
jni4net/jni4net.test.n/src/CallBackTest.cs
Lines 84 to 99 in 8a88cf8
The call loop creates a memory leak in the java vm heap. It seems like JniLocalHandles are not get released by JNI but I will profile this to verify.
Originally posted by @iansmirlis in #1 (comment)
The text was updated successfully, but these errors were encountered: