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.