Time for action – plugging the leak

Now that the leak has been discovered, it needs to be fixed. The solution is to dispose() the Color once it is finished with, which will be when the view itself is removed.

A quick investigation of ClockWidget suggests that overriding dispose() might work. (Note that this is not the correct solution; see later for why.)

  1. Create a dispose() method in ClockWidget with the following code:
    @Override
    public void dispose() {
      if(color != null && !color.isDisposed())
        color.dispose();
      super.dispose();
    }
  2. Run the Eclipse application in debug mode (with the tracing enabled, as before) and open and close the view. The output will show something like:
    There are 87 Color instances
    There are 91 Color instances
    There are 94 Color instances
    There are 98 Color instances
  3. Remove the dispose() method (since it doesn't work as intended) and modify the constructor of ClockWidget to add an anonymous DisposeListener that disposes of the associated Color object:
    public ClockWidget(Composite parent, int style, RGB rgb) {
      super(parent, style);
      this.color = new Color(parent.getDisplay(),rgb);
      addDisposeListener(new DisposeListener() {
        public void widgetDisposed(DisposeEvent e) {
          if(color != null && !color.isDisposed())
            color.dispose();
        }
      });
    }
  4. Now run the code and see what happens when the view is opened and closed a few times:
    There are 87 Color instances
    There are 88 Color instances
    There are 88 Color instances
    There are 88 Color instances

The leak has been plugged.

What just happened?

Once the source of the leak has been identified, the correct course of action is to dispose() the Color object when no longer needed. However, although it is tempting to think that overriding the dispose() method of ClockWidget would be all that is needed, in fact it doesn't work. The only time dispose() is called is at the top level Shell (or ViewPart), and if there are no registered listeners then the dispose method is not called on any components beneath. Since this can be quite counter-intuitive, it is of value to have stepped through code to verify that that is the behavior so that it can be avoided in the future.

Detecting, and resolving, resource leaks can be a time-consuming process. There is a plug-in, developed by the SWT team, which can perform a snapshot of resources and verify whether there are any leaks using a similar technique to the preceding one. The plug-in is located at the SWT tools update site (refer to http://www.eclipse.org/swt/tools.php and search for Sleak for more information) and can be installed to avoid having to modify code (as was done in this example) for the purposes of monitoring allocated resources.

Don't forget when performing tests that the first one or two runs may give different results by virtue of the fact that other resources may be being initialized at the time. Take a couple of readings first before relying on any data, and bear in mind that other plug-ins (that maybe executing in the background) may be doing resource allocation as well.

Finally, when working with any SWT widget, it is good practice to check whether the resource is already disposed or not. The JavaDoc for dispose() says that this is not strictly necessary, and that resources which are already disposed will treat this as a no-op method.

Pop quiz – understanding resources

Q1. Where do resource leaks come from?

Q2. What are the different types of Resources?

Q3. How can you enable SWT resource tracking?

Q4. Once enabled, how do you find out what objects are tracked?

Q5. What's the right way and the wrong way to free resources after use?

Have a go hero – extending the clock widget

Now that the ClockWidget is running, try the following:

  • Write a sleak-like view, which periodically counts allocated objects by type.
  • Modify any text written by acquiring a Font object, with disposal.
  • Create a generic dispose listener that takes an instance of Resource.
  • Provide a setColor() method which allows you to change the color.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset