0

I make an introduction of the scenario:

A web service (SpringMVC) through an action with parameters dynamically generate images with text and returns the response to the client. This service processes about 500 images per minute.

The images are generated with the library SWT [1]. This works fine locally.

To test or production environments, the application is installed on a server without X (CentOS / Ubuntu). And that SWT can draw the images requires the DISPLAY environment variable set correctly. So on the server install Xvfb package to emulate an X environment virtually.

Xvfb: 1-screen 0 1x1x24-dpi 96 &
DISPLAY = localhost: 1.0
export DISPLAY
$TOMCAT/bin/startup.sh

This works fine the first few minutes, but eventually the memory occupied by the Xvfb process grows without limit (from 1 mb to 1.3 Gb and growing ...).

I tried with different configurations and parameters Xvfb [3], but have not had success.

Xvfb: 1-screen 0 1x1x24 -dpi 96 -noreset &
Xvfb: 1-screen 0 1x1x24 -dpi 96 -reset &
Xvfb: 1-screen 0 1x1x24 -dpi 96 -ld 262144 -ls 262144 -lf 1024 &

Took several days with this problem without a solution? I could guide you more try or where freshened?

[1]

public BufferedImage drawImage () {
    // example code, real code is more complex
    FontData [] FontData fontData = new [] {new FontData ("Arial", 8, SWT.NORMAL)};
    Display display = this.getDisplay ();
    Image image = new Image (display, IMAGE_WIDTH, IMAGE_HEIGHT);
    GC gc = new GC (image);
    gc.setAntialias (SWT.ON);
    gc.setInterpolation (SWT.HIGH);
    gc.setBackground (display.getSystemColor (SWT.COLOR_WHITE));
    gc.fillRectangle (0, 0, this.image.getBounds (). width, this.image.getBounds (). height);
    gc.setFont (new Font (display, fontData [0]));
    gc.setForeground (display.getSystemColor (SWT.COLOR_RED));
    gc.drawText ("Text to draw in image", 5, 6);

    BufferedImage bi = null;
    bi = this.convertToAWT (hi.getImage (). getImageData ());
    return bi;
}

@RequestMapping
public void RetrieveImage (HttpServletRequest request, HttpServletResponse response) throws IOException {
    response.setContentType ("image / png");
    BufferedImage image = drawImage ();
    ByteArrayOutputStream os = new ByteArrayOutputStream ();
    ImageIO.write (bi, "png", os);
    InputStream is = new ByteArrayInputStream (os.toByteArray ());
    IOUtils.copy (is, response.getOutputStream ());
}

Update:

Add getDisplay method.

private Display getDisplay() throws DrawImageException {

    if (display == null || display.isDisposed()) {
        LOGGER.debug("Initializing display...");
        try {
            display = Display.getDefault();
        } catch (Exception e) {
            throw new DrawImageException("Can't get default display", e);
        }
    }
    return display;
}

Solved

As Baz and Niranjan said, the problem was with the release of SWT resources. Now work fine.

Community
  • 1
  • 1
  • 1
    Do you dispose the Image instance you create? – Baz Jul 29 '13 at 20:00
  • 1
    Are you disposing `GC` and `Font` as well ? Will `this.getDisplay()` return a new `Display` all the time? If you use the same `Font` for all the images then declare it globally, same is applicable to `Display`. Try running [**Sleak**](http://www.eclipse.org/articles/swt-design-2/sleak.htm) to know how the memory is leaked. Remember in `SWT` `"You have to dispose things which you have created"` – Niranjan Jul 29 '13 at 21:58
  • Blaz, I have reviewed the code, and it was not releasing the instance of Image. Niranjan, I think getDisplay() always returns the same display, and the fonts in the complete method was saving the instance variables, like the colors (swt.Color). I tried to use Sleak, but not only opened the window without any widget inside, I guess it must work fine from a standalone application, not a web. On the other hand I am testing the application with the least (only display), and then I'm adding the text, image and colors progressively. At every step I run a run with JMeter and I monitored the memory. – Ariel Santana Jul 30 '13 at 20:01

0 Answers0