Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 325965 - [Commands] org.eclipse.ui.workbench and org.eclipse.core.expression are preventing the GarbageCollector from removing uninstalled plug-ins
Summary: [Commands] org.eclipse.ui.workbench and org.eclipse.core.expression are preve...
Status: CLOSED WONTFIX
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.6   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Platform UI Triaged CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks:
 
Reported: 2010-09-22 10:00 EDT by Missing name Mising name CLA
Modified: 2019-10-16 08:55 EDT (History)
4 users (show)

See Also:


Attachments
plug-ins for reproduce this bug (13.72 KB, application/zip)
2010-09-22 13:51 EDT, Missing name Mising name CLA
no flags Details
path to gc roots.png (15.74 KB, image/png)
2013-05-14 08:57 EDT, Krzysztof Kazmierczyk CLA
no flags Details
path to gc roots 4.4M1 (59.95 KB, image/png)
2013-10-11 06:11 EDT, Krzysztof Kazmierczyk CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Missing name Mising name CLA 2010-09-22 10:00:05 EDT
Build Identifier: 3.6.0.I20100603-1100

If you stop and uninstall a plug-in that contains a view or editor that was once opened (closed before stop and uninstall was called) something inside the workbench is still holding a reference to the view class. This reference should be replaced by a WeakReference to let the GarbageCollector remove the ClassLoader and the Class if the bundle was uninstalled.

I have found one reference inside the org.eclipse.core.internal.expressions.TypeExtension/ org.eclipse.core.internal.expressions.TypeExtensionManager where the class of the receiver is used as a key for the fTypeExtensionMap. But there is still other references which prevent the GarbageCollector from removing uninstalled plug-ins.


Reproducible: Always

Steps to Reproduce:
1. Create a plug-in (test.holder) with a holder class that holds an array of WeakReferences<Class<?>>
2. Create a thread that checks that array of WeakReferences<Class<?>> to see if the GarbageCollector has already removed the Class inside the WeakReference.
3. create a plug-in (test.view) with a simple view
4. inside the createPartControl() method of the view add the class of the view to the previously create array of WeakReferences
5. open the view via the menu
6. close the view
7. stop the plug-in (test.view) with the osgi console
8. uninstall the plug-in (test.view) with the osgi console
9. request some GarbageCollection (4-5 times) with the osgi console
10. check the array of WeakReferences<Class<?>> inside the test-holder plug-in and you will see that this class will never be removed


If you replace the text.view – plug-in with a small osgi bundle that registers a class from its bundle on activation and run the stop and uninstall steps again you will see that this class will be gone after some gc-calls.
Comment 1 Missing name Mising name CLA 2010-09-22 10:01:16 EDT
If you like I can create a small test scenario and add it to this bug.
Comment 2 Remy Suen CLA 2010-09-22 10:05:26 EDT
(In reply to comment #1)
> If you like I can create a small test scenario and add it to this bug.

Such contributions are always welcome.
Comment 3 Missing name Mising name CLA 2010-09-22 13:51:40 EDT
Created attachment 179397 [details]
plug-ins for reproduce this bug

This Zip contains 4 projects:

- test.holder: plug-in holding the WeakReference and a small OSGi Commandline extension for printing some memory information
- test.simple.osgi: simple plug-in using only osgi (this works correct)
- test.simple.view: simple view (this is not working correct)
- test.run.configs: contains two launch configurations
  + Eclipse View Test: Launch config for not working example
  + OSGi Test: Launch config for working example
Comment 4 Missing name Mising name CLA 2010-09-22 13:59:48 EDT
The test.holder plug-in holds WeakReference to classes you specify and a Thread inside this plug-in will remove does WeakReferences if the class is unloaded by the GarbageCollector.

I've also added a OSGi CommandProvider so you can display all specified class references inside the test.holder and if it's required fill the memory with some content to try to force the GarbageCollector to run.

---Command's for ClassReferenceHolder---
  print - prints the content of the ClassReferenceHolder array
  fillMemory <memory-in-byte> - allocate some memory for trying to start the gc earlier
  freeMemory - free the memory allocated with fillMemory <memory-in-byte>
  printMemory - print the memory usage of the JVM
Comment 5 Krzysztof Kazmierczyk CLA 2013-05-14 08:32:17 EDT
I was able to reproduce the issue.

I see that following objects of following classes are keeping the reference to SimpleTestView object:

 - org.eclipse.core.runtime.ListenerList
 - org.Eclipse.ui.ViewPart$1
 - org.eclipse.core.internal.registry.ConfigurationElementHandle
 - org.eclipse.ui.internal.ViewSite

By the way. Rene, are you using OSGI console in your product? Are you uninstalling the plugins in runtime? Or you just have noticed such issue and decided to fill the defect?
Comment 6 Krzysztof Kazmierczyk CLA 2013-05-14 08:57:00 EDT
Created attachment 230935 [details]
path to gc roots.png

Sorry for typo in my previous comment. I provided there the list of the objects for which SimpleTestView is still keeping references.

Attaching path to GC root. It seems that this reference is kept by CompatibilityView.
Comment 7 Krzysztof Kazmierczyk CLA 2013-05-15 11:28:08 EDT
I performed following test today:
1. Opened view => The number of org.eclipse.ui.internal.e4.compatibility.CompatibilityPart objects increased by 1
2. Closed view and ran gc() => the number remained the same
3. Opened view => The number of org.eclipse.ui.internal.e4.compatibility.CompatibilityPart objects increased by 1 comparing to the number from step 2
4. Closed view and ran gc() => the number decreased by 1 comparing to the number at the end of step 3
5. Opened view => The number of org.eclipse.ui.internal.e4.compatibility.CompatibilityPart objects increased by 1 comparing to number from step 4
6. Closed view and ran gc() => the number decreased by 1 comparing to the number at the end of step 5

This indicates that CompatibilityPart object is not released first time only.
Comment 8 Krzysztof Kazmierczyk CLA 2013-09-16 07:43:18 EDT
I have further investigated it a bit.

1. I noticed that first time when I close view, there is no instance of the object released.
2. When closing next time, it is gc released the instance created in the previous cycle.
3. The previous instance of the object is ready to be disposed before test.simple.view.SimpleTestView.dispose() is reached. It can be GCed even before org.eclipse.swt.custom.CTabFolder$1.handleEvent(org.eclipse.swt.widgets.Event) line: 283 is executed.

Here is full stack trace from SimpleTestView.dispose() method:


test.simple.view.SimpleTestView.dispose() line: 36	
org.eclipse.ui.internal.e4.compatibility.CompatibilityView(org.eclipse.ui.internal.e4.compatibility.CompatibilityPart).invalidate() line: 226	
org.eclipse.ui.internal.e4.compatibility.CompatibilityView(org.eclipse.ui.internal.e4.compatibility.CompatibilityPart).destroy() line: 392	
sun.reflect.NativeMethodAccessorImpl.invoke0(java.lang.reflect.Method, java.lang.Object, java.lang.Object[]) line: not available [native method]	
sun.reflect.NativeMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) line: 60	
sun.reflect.DelegatingMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) line: 37	
java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object...) line: 611	
org.eclipse.e4.core.internal.di.MethodRequestor.execute() line: 56	
org.eclipse.e4.core.internal.di.InjectorImpl.processAnnotated(java.lang.Class<? extends java.lang.annotation.Annotation>, java.lang.Object, java.lang.Class<?>, org.eclipse.e4.core.di.suppliers.PrimaryObjectSupplier, org.eclipse.e4.core.di.suppliers.PrimaryObjectSupplier, java.util.ArrayList<java.lang.Class<?>>) line: 877	
org.eclipse.e4.core.internal.di.InjectorImpl.processAnnotated(java.lang.Class<? extends java.lang.annotation.Annotation>, java.lang.Object, java.lang.Class<?>, org.eclipse.e4.core.di.suppliers.PrimaryObjectSupplier, org.eclipse.e4.core.di.suppliers.PrimaryObjectSupplier, java.util.ArrayList<java.lang.Class<?>>) line: 857	
org.eclipse.e4.core.internal.di.InjectorImpl.uninject(java.lang.Object, org.eclipse.e4.core.di.suppliers.PrimaryObjectSupplier) line: 179	
org.eclipse.e4.core.internal.di.FieldRequestor(org.eclipse.e4.core.internal.di.Requestor).uninject(java.lang.Object, org.eclipse.e4.core.di.suppliers.PrimaryObjectSupplier) line: 142	
org.eclipse.e4.core.internal.contexts.ContextObjectSupplier$ContextInjectionListener.update(org.eclipse.e4.core.contexts.IEclipseContext, int, java.lang.Object[]) line: 82	
org.eclipse.e4.core.internal.contexts.TrackableComputationExt.update(org.eclipse.e4.core.internal.contexts.ContextChangeEvent) line: 107	
org.eclipse.e4.core.internal.contexts.EclipseContext.removeListenersTo(java.lang.Object) line: 456	
org.eclipse.e4.core.contexts.ContextInjectionFactory.uninject(java.lang.Object, org.eclipse.e4.core.contexts.IEclipseContext) line: 144	
org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeRemoveGui(org.eclipse.e4.ui.model.application.ui.MUIElement) line: 908	
org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$3(org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine, org.eclipse.e4.ui.model.application.ui.MUIElement) line: 828	
org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$8.run() line: 823	
org.eclipse.core.runtime.SafeRunner.run(org.eclipse.core.runtime.ISafeRunnable) line: 42	
org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.removeGui(org.eclipse.e4.ui.model.application.ui.MUIElement) line: 808	
org.eclipse.e4.ui.workbench.renderers.swt.ElementReferenceRenderer.disposeWidget(org.eclipse.e4.ui.model.application.ui.MUIElement) line: 109	
org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeRemoveGui(org.eclipse.e4.ui.model.application.ui.MUIElement) line: 899	
org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$3(org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine, org.eclipse.e4.ui.model.application.ui.MUIElement) line: 828	
org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$8.run() line: 823	
org.eclipse.core.runtime.SafeRunner.run(org.eclipse.core.runtime.ISafeRunnable) line: 42	
org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.removeGui(org.eclipse.e4.ui.model.application.ui.MUIElement) line: 808	
org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$1.handleEvent(org.osgi.service.event.Event) line: 153	
org.eclipse.e4.ui.services.internal.events.UIEventHandler$1.run() line: 41	
org.eclipse.ui.internal.UISynchronizer(org.eclipse.swt.widgets.Synchronizer).syncExec(java.lang.Runnable) line: 180	
org.eclipse.ui.internal.UISynchronizer.syncExec(java.lang.Runnable) line: 150	
org.eclipse.swt.widgets.Display.syncExec(java.lang.Runnable) line: 4688	
org.eclipse.e4.ui.internal.workbench.swt.E4Application$1.syncExec(java.lang.Runnable) line: 205	
org.eclipse.e4.ui.services.internal.events.UIEventHandler.handleEvent(org.osgi.service.event.Event) line: 38	
org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(org.osgi.service.event.Event, java.security.Permission) line: 197	
org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(org.eclipse.equinox.internal.event.EventHandlerWrapper, java.security.Permission, int, org.osgi.service.event.Event) line: 197	
org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(java.lang.Object, java.lang.Object, int, java.lang.Object) line: 1	
org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(java.util.Set<java.util.Map.Entry<K,V>>, org.eclipse.osgi.framework.eventmgr.EventDispatcher<K,V,E>, int, E) line: 230	
org.eclipse.osgi.framework.eventmgr.ListenerQueue<K,V,E>.dispatchEventSynchronous(int, E) line: 148	
org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(org.osgi.service.event.Event, boolean) line: 135	
org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(org.osgi.service.event.Event) line: 78	
org.eclipse.equinox.internal.event.EventComponent.sendEvent(org.osgi.service.event.Event) line: 39	
org.eclipse.e4.ui.services.internal.events.EventBroker.send(java.lang.String, java.lang.Object) line: 80	
org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(org.eclipse.emf.common.notify.Notification) line: 58	
org.eclipse.e4.ui.model.application.ui.advanced.impl.PlaceholderImpl(org.eclipse.emf.common.notify.impl.BasicNotifierImpl).eNotify(org.eclipse.emf.common.notify.Notification) line: 374	
org.eclipse.e4.ui.model.application.ui.advanced.impl.PlaceholderImpl(org.eclipse.e4.ui.model.application.ui.impl.UIElementImpl).setToBeRendered(boolean) line: 290	
org.eclipse.e4.ui.internal.workbench.PartServiceImpl.hidePart(org.eclipse.e4.ui.model.application.ui.basic.MPart, boolean) line: 1169	
org.eclipse.e4.ui.internal.workbench.PartServiceImpl.hidePart(org.eclipse.e4.ui.model.application.ui.basic.MPart) line: 1101	
org.eclipse.e4.ui.workbench.renderers.swt.StackRenderer.closePart(org.eclipse.swt.widgets.Widget, boolean) line: 1111	
org.eclipse.e4.ui.workbench.renderers.swt.StackRenderer.access$5(org.eclipse.e4.ui.workbench.renderers.swt.StackRenderer, org.eclipse.swt.widgets.Widget, boolean) line: 1093	
org.eclipse.e4.ui.workbench.renderers.swt.StackRenderer$12.close(org.eclipse.swt.custom.CTabFolderEvent) line: 987	
org.eclipse.swt.custom.CTabFolder.onMouse(org.eclipse.swt.widgets.Event) line: 1833	
org.eclipse.swt.custom.CTabFolder$1.handleEvent(org.eclipse.swt.widgets.Event) line: 283 => the previous instance of SimpleTestView can be GCed even on this level of the stack
org.eclipse.swt.widgets.EventTable.sendEvent(org.eclipse.swt.widgets.Event) line: 84	
org.eclipse.swt.custom.CTabFolderCTabFolder(org.eclipse.swt.widgets.Widget).sendEvent(org.eclipse.swt.widgets.Event) line: 1058	
org.eclipse.swt.widgets.Display.runDeferredEvents() line: 4170	
org.eclipse.swt.widgets.Display.readAndDispatch() line: 3759	
org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run() line: 1113	
org.eclipse.core.databinding.observable.Realm.runWithDefault(org.eclipse.core.databinding.observable.Realm, java.lang.Runnable) line: 332	
org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(org.eclipse.e4.ui.model.application.MApplicationElement, org.eclipse.e4.core.contexts.IEclipseContext) line: 997	
org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(org.eclipse.e4.ui.model.application.MApplicationElement) line: 138	
org.eclipse.ui.internal.Workbench$5.run() line: 613	
org.eclipse.core.databinding.observable.Realm.runWithDefault(org.eclipse.core.databinding.observable.Realm, java.lang.Runnable) line: 332	
org.eclipse.ui.internal.Workbench.createAndRunWorkbench(org.eclipse.swt.widgets.Display, org.eclipse.ui.application.WorkbenchAdvisor) line: 567	
org.eclipse.ui.PlatformUI.createAndRunWorkbench(org.eclipse.swt.widgets.Display, org.eclipse.ui.application.WorkbenchAdvisor) line: 150	
org.eclipse.ui.internal.ide.application.IDEApplication.start(org.eclipse.equinox.app.IApplicationContext) line: 124	
org.eclipse.equinox.internal.app.EclipseAppHandle.run(java.lang.Object) line: 196	
org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(java.lang.Object) line: 109	
org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(java.lang.Object) line: 80	
org.eclipse.core.runtime.adaptor.EclipseStarter.run(java.lang.Object) line: 372	
org.eclipse.core.runtime.adaptor.EclipseStarter.run(java.lang.String[], java.lang.Runnable) line: 226	
sun.reflect.NativeMethodAccessorImpl.invoke0(java.lang.reflect.Method, java.lang.Object, java.lang.Object[]) line: not available [native method]	
sun.reflect.NativeMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) line: 60	
sun.reflect.DelegatingMethodAccessorImpl.invoke(java.lang.Object, java.lang.Object[]) line: 37	
java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object...) line: 611	
org.eclipse.equinox.launcher.Main.invokeFramework(java.lang.String[], java.net.URL[]) line: 636	
org.eclipse.equinox.launcher.Main.basicRun(java.lang.String[]) line: 591	
org.eclipse.equinox.launcher.Main.run(java.lang.String[]) line: 1450	
org.eclipse.equinox.launcher.Main.main(java.lang.String[]) line: 1426
Comment 9 Krzysztof Kazmierczyk CLA 2013-10-11 06:11:59 EDT
Created attachment 236369 [details]
path to gc roots 4.4M1

I have generated another path to gc roots when the view is closed and had a bit different than in this one in comment 6.
Comment 10 Lars Vogel CLA 2016-04-20 12:13:37 EDT
Mass move to 4.7 as M7 is approaching. Please move back in case you are planning to fix it for Neon.
Comment 11 Eclipse Genie CLA 2019-10-16 08:55:29 EDT
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.