Bug 570645 - nondisposetracker should say what resource was not disposed
Summary: nondisposetracker should say what resource was not disposed
Status: NEW
Alias: None
Product: Platform
Classification: Eclipse Project
Component: IDE (show other bugs)
Version: 4.19   Edit
Hardware: PC All
: P3 enhancement with 2 votes (vote)
Target Milestone: ---   Edit
Assignee: Platform-UI-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-01-25 17:39 EST by Wim Jongman CLA
Modified: 2021-10-14 17:03 EDT (History)
4 users (show)

See Also:


Attachments
Screenshot of Flightrecorded Errors of eclipseI20210703.png (80.16 KB, image/png)
2021-07-03 18:03 EDT, Jörg Kubitz CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Wim Jongman CLA 2021-01-25 17:39:26 EST
As can be seen from the stack trace in [1], it can be quite a puzzle to find where the resource was actually created.

java.lang.Error: SWT Resource was not properly disposed

It might help if the Error sent by the tracker would say what kind of resource was not disposed of:

e.g. 
java.lang.Error: SWT Resource (Image) was not properly disposed



[1] https://bugs.eclipse.org/bugs/attachment.cgi?id=285381
Comment 1 Andrey Loskutov CLA 2021-01-25 18:09:00 EST
I think this should be fixed in IDE, not SWT. We can walk exception stack trace down and add the right class before logging to Eclipse log. The reason is to reduce possible overhead on creation for every resource and to have it only for few found leaked resources only.
Comment 2 Uwe BR CLA 2021-03-08 00:20:27 EST
I find in 10 to 30 Log messages with this kind of error. My session Data are:

eclipse.buildId=4.19.0.I20210224-1800
java.version=15.0.2
java.vendor=Oracle Corporation
BootLoader constants: OS=win32, ARCH=x86_64, WS=win32, NL=de_DE
Framework arguments:  -product org.eclipse.epp.package.jee.product -product org.eclipse.epp.package.jee.product
Command-line arguments:  -os win32 -ws win32 -arch x86_64 -product org.eclipse.epp.package.jee.product -data file:/D:/workspace2019/ -product org.eclipse.epp.package.jee.product

and the Stack Trace:

java.lang.Error: SWT Resource was not properly disposed
	at org.eclipse.swt.graphics.Resource.initNonDisposeTracking(Resource.java:172)
	at org.eclipse.swt.graphics.Resource.<init>(Resource.java:120)
	at org.eclipse.swt.graphics.Image.<init>(Image.java:205)
	at com.codeaffine.eclipse.swt.widget.scrollbar.ImageDrawer.draw(ImageDrawer.java:64)
	at com.codeaffine.eclipse.swt.widget.scrollbar.ImageUpdate.update(ImageUpdate.java:52)
	at com.codeaffine.eclipse.swt.widget.scrollbar.ClickControl.controlResized(ClickControl.java:52)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:239)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4209)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1043)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1067)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1048)
	at org.eclipse.swt.widgets.Control.WM_SIZE(Control.java:5462)
	at org.eclipse.swt.widgets.Label.WM_SIZE(Label.java:481)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4837)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4930)
	at org.eclipse.swt.internal.win32.OS.CallWindowProc(Native Method)
	at org.eclipse.swt.widgets.Label.callWindowProc(Label.java:123)
	at org.eclipse.swt.widgets.Control.WM_WINDOWPOSCHANGED(Control.java:5692)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4850)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4938)
	at org.eclipse.swt.internal.win32.OS.SetWindowPos(Native Method)
	at org.eclipse.swt.widgets.Control.setBoundsInPixels(Control.java:3272)
	at org.eclipse.swt.widgets.Control.setBoundsInPixels(Control.java:3233)
	at org.eclipse.swt.widgets.Control.setBoundsInPixels(Control.java:3229)
	at org.eclipse.swt.widgets.Control.setBoundsInPixels(Control.java:3305)
	at org.eclipse.swt.widgets.Control.setBounds(Control.java:3301)
	at com.codeaffine.eclipse.swt.widget.scrollbar.Direction.applyComponentBounds(Direction.java:171)
	at com.codeaffine.eclipse.swt.widget.scrollbar.Direction.access$3(Direction.java:169)
	at com.codeaffine.eclipse.swt.widget.scrollbar.Direction$2.layout(Direction.java:84)
	at com.codeaffine.eclipse.swt.widget.scrollbar.FlatScrollBar.layout(FlatScrollBar.java:201)
	at com.codeaffine.eclipse.swt.widget.scrollbar.FlatScrollBar.setMaximum(FlatScrollBar.java:123)
	at com.codeaffine.eclipse.swt.widget.scrollable.TreeVerticalScrollBarUpdater.updateScrollbar(TreeVerticalScrollBarUpdater.java:47)
	at com.codeaffine.eclipse.swt.widget.scrollable.TreeVerticalScrollBarUpdater.update(TreeVerticalScrollBarUpdater.java:39)
	at com.codeaffine.eclipse.swt.widget.scrollable.WatchDog.doRun(WatchDog.java:111)
	at com.codeaffine.eclipse.swt.widget.scrollable.WatchDog.lambda$0(WatchDog.java:97)
	at com.codeaffine.eclipse.swt.widget.scrollable.context.Reconciliation.runWhileSuspended(Reconciliation.java:62)
	at com.codeaffine.eclipse.swt.widget.scrollable.WatchDog.runWithReconciliationSuspended(WatchDog.java:97)
	at com.codeaffine.eclipse.swt.widget.scrollable.WatchDog.run(WatchDog.java:91)
	at org.eclipse.swt.widgets.Display.runTimer(Display.java:4124)
	at org.eclipse.swt.widgets.Display.messageProc(Display.java:3256)
	at org.eclipse.swt.internal.win32.OS.DispatchMessage(Native Method)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3624)
	at org.eclipse.jface.window.Window.runEventLoop(Window.java:823)
	at org.eclipse.jface.window.Window.open(Window.java:799)
	at org.tigris.subversion.subclipse.ui.dialogs.ChooseUrlDialog.open(ChooseUrlDialog.java:289)
	at org.tigris.subversion.subclipse.ui.wizards.dialogs.SvnWizardSwitchPage$2.widgetSelected(SvnWizardSwitchPage.java:169)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:252)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4209)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1043)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4026)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3626)
	at org.eclipse.jface.window.Window.runEventLoop(Window.java:823)
	at org.eclipse.jface.window.Window.open(Window.java:799)
	at org.tigris.subversion.subclipse.ui.actions.SwitchAction.execute(SwitchAction.java:50)
	at org.tigris.subversion.subclipse.ui.actions.SVNAction.run(SVNAction.java:51)
	at org.eclipse.ui.actions.ActionDelegate.runWithEvent(ActionDelegate.java:76)
	at org.eclipse.ui.internal.PluginAction.runWithEvent(PluginAction.java:229)
	at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:580)
	at org.eclipse.jface.action.ActionContributionItem.lambda$4(ActionContributionItem.java:414)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4209)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1043)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4026)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3626)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1157)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1046)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
	at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:644)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:551)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:156)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:152)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:653)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:590)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1461)
Comment 3 Jörg Kubitz CLA 2021-07-03 18:03:18 EDT
Created attachment 286723 [details]
Screenshot of Flightrecorded Errors of eclipseI20210703.png

I get 581 Errors "SWT Resource was not properly disposed" when i start a plain eclipse with empty workspace. (build I20210703) 

1. Is some already investigating all those? If not: is it needed to create a separate bug for each different stacktrace?

Steps to reproduce:

 eclipse.exe -vmargs -XX:+FlightRecorder -XX:StartFlightRecording=duration=10s,filename=myrecording.jfr -XX:FlightRecorderOptions=stackdepth=1000

 Wait 10 seconds

 Close eclipse

 Open "myrecording.jfr" with JDK Mission Control

One the one hand it is lucky(?) for finding those that they are of type Error - as those are reported by flightrecoreder without further configuration. On the other hand an "Error" is meant to be not catchable - which is semantically wrong here. They are not even thrown.
2. Instead of remembering an java.lang.Error i suggest to remember a dedicated NotDisposedThrowable to being able to separate them in the Exception dumps from other Errors.

3. I suggest to put Resource.class.simplename in the message which would probably fullfill this change request in terms of type of the resource.

4. The particular name of the resource could be added by adding a default String getDisposeName() to the interface wich could be overloaded for example by return FontData.name. That would fullfill this bugs change requested.

5. finalize() is deprecated. It would be better to use a dedicated phantom reference queue. The reasons in short: If one queue screws up it does not hang up other bad finalisers with it.

6. BTW is somebody looking at those other errors (java.lang.NoSuchMethodError, 	
java.lang.IncompatibleClassChangeError, java.lang.UnsatisfiedLinkError)?

7. Is it really wanted to distribute the reportNonDisposed=true in the builds? To me it sounds more like a debug option which is typically disabled by default. Kinda odd to see them used in deployments like https://stackoverflow.com/questions/67419601/

8. Is there any eclipse.exe junit test which could be extended to report such startup-errors automatically?

I was not hunting for errors i only wanted to sample the the startup performance. I was a bit shocked by all those errors. To quote JDK Mission control:
"625 errors were thrown in total. The most common error was ''java.lang.Error'', which was thrown 581 times. Investigate the thrown errors to see if they can be avoided. Errors indicate that something went wrong with the code execution and should never be used for flow control."
Comment 4 Andrey Loskutov CLA 2021-07-03 18:30:42 EDT
Jörg, I assume 581 exceptions was created, but none reported to the log, right? If so, it is expected, if the reportNonDisposed=true is set, and doesn't mean any leak. Only reported exceptions are to be investigated/leaks fixed, and yes, at least I try to report and fix them. 

Regarding use of this flag - it is up to products to define which settings/flags are enabled or not. For normal use case, there is no difference in performance or memory load with the flag enabled.

Regarding unit tests - in eclipse.org tests we don't monitor errors in the log,  it would be nice, but it requires lot of work. We at Advantest monitor logs and automatically fail unit tests on unexpected errors/warnings in the log, and found already few leaks with this.

For all other exceptions - feel free to investigate / report *dedicated* bugs.
Comment 5 Jörg Kubitz CLA 2021-07-03 18:54:17 EDT
(In reply to Andrey Loskutov from comment #4)
> Jörg, I assume 581 exceptions was created, but none reported to the log,

Which file would i need to inspect? The eclipse error view is empty. Nevertheless i guess they are only not reported for other reasons - as only the default fonts should be expected to not not disposed (and shout not create a stacktrace either).

> settings/flags are enabled or not. For normal use case, there is no
> difference in performance or memory load with the flag enabled.

"no difference" i doubt. Some microseconds per exceptions i guess. I am less concerned of the overhead then of the "bad light" it throws on a product which produces so much errors.

> Regarding unit tests - in eclipse.org tests we don't monitor errors in the
> log,  it would be nice, but it requires lot of work. 

As shown above errors can be recorded with the openjdks build in flightrecorder. Sounds much easier then parsing logs.

> For all other exceptions - feel free to investigate / report *dedicated*
> bugs.

Do you mean 1 bug per stacktrace? I don't want to spam.
Comment 6 Jörg Kubitz CLA 2021-07-04 12:20:43 EDT
(In reply to Jörg Kubitz from comment #3)
> Created attachment 286723 [details]
> Screenshot of Flightrecorded Errors of eclipseI20210703.png
> 
> I get 581 Errors "SWT Resource was not properly disposed" when i start a
> plain eclipse with empty workspace. (build I20210703) 


Those Error class instance numbers are misleading: The errors are currently created no matter whether the resource was disposed or not. I am sorry for confusion.