Closed raghucssit closed 5 months ago
This issue is introduced after this https://github.com/eclipse/swtchart/issues/289 There are cases where chart is disposed and it's children are not which I mentioned above.
@raghucssit Thanks for reporting it. Could you create a demo to show this case, like:
org.eclipse.swtchart.extensions.examples.charts.DemoChart.java
If I remember right, the problem is observed in the code of a view (not editor like in #289) that is being closed. In this case, the parent control given to view on createPartControl() is disposed early and also disposes all created children - so that the actual dispose() method of the chart is called on already disposed chart object, so it can't dispose created objects.
Yep, we see it from time to time, especially when closing applications. Anyways, as soon as we figured out how to reproduce it, we are able to write a fix.
bar-chart-view.zip Please import this plugin and launch a new run time from the plugin. Open the view "Bar Chart View", a bart can be seen. Then close the view we can see resource leak.
Below View class can reproduce the issue.
` public class BarChartView extends ViewPart {
/**
* The ID of the view as specified by the extension.
*/
public static final String ID = "chartvew.views.BarChartView";
private Chart chart;
private static final double[] ySeries = { 0.2, 1.1, 1.9, 2.3, 1.8, 1.5, 1.8, 2.6, 2.9, 3.2 };
@Override
public void createPartControl(Composite parent) {
// create a chart
chart = new Chart(parent, SWT.NONE);
// set titles
chart.getTitle().setText("Bar Chart");
chart.getAxisSet().getXAxis(0).getTitle().setText("Data Points");
chart.getAxisSet().getYAxis(0).getTitle().setText("Amplitude");
// create bar series
IBarSeries<?> barSeries = (IBarSeries<?>) chart.getSeriesSet().createSeries(SeriesType.BAR, "bar series");
barSeries.setYSeries(ySeries);
// adjust the axis range
chart.getAxisSet().adjustRange();
parent.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
// This method is called before dispose() is called. This will dispose the chart
// also making chart.dispose() in dispose() method useless.
return;
}
});
}
@Override
public void dispose() {
// this dispose has no effect as the chart is already disposed.
chart.dispose();
// usually when system does gc errors will be reported in error log. This GC
// call may not guarantee immediate GC so soon it can report error.
System.gc();
super.dispose();
}
@Override
public void setFocus() {
chart.setFocus();
}
}
`
Note, Eclipse JVM must be started with -Dorg.eclipse.swt.graphics.Resource.reportNonDisposed=true
argument (default in SDK) to see SWT resource leaks reported.
@eselmeister Please check my project to reproduce the issue. If there is any problem with the project or steps please let me know.
Yes, I have your issue on the radar.
@raghucssit I have created a test case, based on your data, which can be used to create a crash and imitate the Eclipse View part. So far, the "Dispose Listener" is called and the chart is disposed correctly.
You can start the DemoChartDialog
as a simple "Java Application"
@eselmeister Yes i have tried with sample RCP. It works as you said. But when we use it with views Chart#dispose() is called after chart's parent widget is disposed.
Problem: We can create a chart on a shell on any composite on eclipse views. A shell can be opened from eclipse platform in the form of dialog/Any view can be populated and closed. Use cases are like showing some data chart on a separate window/view. User can usually close Window/View. In this case a View is disposed first and subsequently Chart as well.This Chart disposal does not invoke
Chart.dispose()
. Any later atempt to dispose the chart does not clear below resourcesif(!isDisposed()) { title.dispose(); legend.dispose(); axisSet.dispose(); super.dispose(); }
.Work around seems to be adding the dispose listener to parent and dispose the chart. Or adding the dispose listener to chart and dispose the resources.