Community
Participate
Working Groups
Build Identifier: Deleted ProjectSpaces and Projects stay in memory forever as well as all included model elements. The problem is actual for both server and client. The attached patch solves the problem. For some reason, it cannot be applied with (my) git, works without problems in Eclipse. It should be applied on the workspace root, with option "Ignoring leading path name segments" set to 1 To archieve the result the following actions are performed. 1. All resources are deleted after deletion of ProjectSpace and Project. 2. OperationRecorder.emfStoreCommandStack on the client is cleared 3. WorkspaceManager.observerBus on the client is cleared 4. ECrossReferenceAdapter on the client is extended to delete all resources of a deleted project from map unloadedResource Reproducible: Always Steps to Reproduce: Project stays in memory after deletion on the server 1. Import a project from a file. 2. Share it to the server. 3. Delete the project from the server Server uses more memory than it used before. Project stays in memory after deletion on the client 1. Checkout a project from the server. 2. Delete the project from the workspace. Client uses more memory than it used before.
Created attachment 213376 [details] A patch, removing memory leaks
Patch has been applied and tested with slight modifications. Thanks for the contribution.
The problem is reproduced on the client. Line WorkspaceManager.getObserverBus().unregister(this, LoginObserver.class); has to be in the method ProjectSpaceBase.delete() as it was proposed in the patch, or method ObserverBus.unregister(IObsever) has to be fixed, because invocation WorkspaceManager.getObserverBus().unregister(this) doesn't remove ProjectSpace from the ObserverBus. Method unregister(IObsever observer) supposes that the ProjectSpace is registered for one of interfaces, implemented by the observer
Ok, well I'll change the line to WorkspaceManager.getObserverBus().unregister(this, LoginObserver.class) then. I propose that you create a new bug report, since in my understanding ObserverBus#unregister is not working as expected. Please describe the issue there. I'll close this bug report as soon as the mentioned line has been changed and pushed.
No, as far as I have understood, ObserverBus#unregister is expected to work exactly so. And the bug report is not required. /** * Unregisters an observer for all observer interfaces implemented by the object or its super classes. * * @param observer observer object */ public void unregister(IObserver observer) { ... /** * Registers an observer for all observer interfaces implemented by the object or its super classes. * * @param observer observer object */ public void register(IObserver observer) { ...
Sorry, I don't get it yet. If ProjectSpace implements LoginObserver and ProjectSpaceImpl extends ProjectSpaceBase then in my understanding a call to getObserverBus().unregister(this) in ProjectSpaceBase must remove the ProjectSpace instance from the ObserverBus. This is also what the javadoc says you've pasted. So why should there be a difference between unregister(this) and unregister(this, LoginObserver.class) regarding the unsubscription of the LoginObserver only.
For refernce: Assuming that DImpl extends CImpl the following test would fail: public void testSuperUnregister() { DImpl d = new DImpl(); getObserverBus().register(d, C.class); assertEquals("42", getObserverBus().notify(C.class).fourtyTwo()); getObserverBus().unregister(d); assertFalse("42".equals(getObserverBus().notify(C.class).fourtyTwo())); } I'll contact Otto, who wrote the ObserverBus whether this is intended behaviour.
Yes, you are right, I didn't see that ProjectSpaceBase implements LoginObserver.
Obviously, method ObserverBus#getClasses is wrong. You could use, for example ClassUtils#getAllInterfaces(Class cls) from org.apache.commons instead
I've fixed the getClasses call by implementing our own getAllInterfaces method in ObserverBus directly. I'd to close this ticket, since my proposed test works as we'd have expected. But just to go sure, can you re-test, i.e. check whether the memory leak is gone now?