Community
Participate
Working Groups
Created attachment 282231 [details] the static map which is not cleared.
Created attachment 282232 [details] visualvm memory dump
As discussed in the forum[1], the keys of this map are weakened, so en entry will be removed automatically when its key is garbage collected. What is the context, i.e. when does a memory leak happen? Looking at this memory snapshot, there is still a ZestFxRootPart present. That should be disposed when calling IViewer.dispose(). So you should find out why it is not garbage collected. (And maybe you can find a minimal leaking example.) I would rather not provide means to clear the map as a last resort. Maybe we have to, though. [1] https://www.eclipse.org/forums/index.php/t/1101831/
Hi Matthias, There was some issue with my code, preDestroy() call which sets the viewer reference to null was not getting called. After fixing the issue and waiting for around 2 hours for GC to collect keys of weak hashmap, it indeed clears the keys. Now ApaptableScope map is no loger holding the refernce of javafx objets. But still the leak exists (Please refer attached screenshot) Any idea why this leak exists ? Context : I have a javafx application rendered in a FXCanvas which is child of a eclipse component (our product component). Whenever i invoke the javafx feature and close it, this issue happens. Thanks and Regards, Giri
Created attachment 282241 [details] GC root showing reference held by launcher
Thanks for sharing additional insights. Alexander tried to come up with a test case to ensure that this map is cleared as it should be. However, he could not yet make it work, and neither could I. While experimenting, it seems like the scopedInstances map strangely reports its size in comparison to its keySet() and values() (no keys, no values, but size=1). Looking into a heap dump reveals that the key is removed, but the stored value somehow remains in a "segments" table (I will have to investigate further). I experimented with different weak hash map implementations and noticed different behaviors. I cannot yet conclude how to proceed. As a workaround, you can clear the map using reflection, somewhat like this: Class adaptableScopeClass = AdaptableScope.typed(IDomain.class).getClass(); Field scopedInstances = adaptableScopeClass.getDeclaredField("scopedInstances"); scopedInstances.setAccessible(true); scopedInstances.get(null).clear();
Thanks for the analysis Matthias. I tried to clear the map using reflection but i get following compilation error. Am i doing something wrong ? The type AdaptableScope<IDomain> is not visible Thanks and Regards, Giri
You cannot import the class as it has package visibility. What you can do is: Object rootScope = AdaptableScopes.typed(Root.class); assertNotNull(rootScope); Field scopedInstancesField = rootScope.getClass() .getDeclaredField("scopedInstances"); scopedInstancesField.setAccessible(true); @SuppressWarnings("unchecked") Map<IAdaptable, Map<Key<?>, Object>> scopedInstances = (Map<IAdaptable, Map<Key<?>, Object>>) scopedInstancesField.get(null);
The first line has to be replace with an Object variable pointing to the AdapterScope you use.
I already posted that code in the comment above, but with a typo: AdaptableScope vs. AdaptableScopes. There I used IDomain.class, because that should be present.