See my post earlier on memory leaks - I had trouble with Images like
this in IE as well.

I suggest you try:

1) re-creating the Image every time instead of using setUrl()
2) when removing the Image, call into a purge references method like
this:

  /**
   * Gratefully taken from http://javascript.crockford.com/memory/leak.html
   */
  public native static void purge( Element d ) /*-{
        var a = d.attributes, i, l, n;
        if (a) {
            l = a.length;
            for (i = 0; i < l; i += 1) {
                n = a[i].name;
                if (typeof d[n] === 'function') {
                    d[n] = null;
                }
            }
        }
        a = d.childNodes;
        if (a) {
            l = a.length;
            for (i = 0; i < l; i += 1) {
                purge(d.childNodes[i]);
            }
        }
  }-*/;

3) I do that with a special Image subclass:

public class NoMemLeakImage extends Image {

  public NoMemLeakImage() {
    super();
  }

  public NoMemLeakImage( String imageURL ) {
    super( imageURL );
  }

  @Override protected void onDetach() {
    try {
      super.onDetach();
    } finally {
      //  IE7 seems to leave onabort, __kids and __cleanup pointing
      //  into javascript & causing a circular reference here.  Just
      //  wipe everything.on detach.
      DOMHelpers.purge( getElement() );

      // TODO: This seems a little unsafe.  Specifically - if you re-
attach
      // TODO: the image later, we don't re-set-up the event handlers.
    }
  }
}

Regards,
Paul


On Nov 1, 10:06 am, hermis <[email protected]> wrote:
> Hello,
>
> I have written a simple application which fills a FlexTable with a set
> of images. There is a timer which updates the URL of each image every
> second. The URL points to a Servlet which in turn generates a random
> PNG image on its doGet() method and writes it to the response output
> stream. The servlet sets the "Cache-Control" header to "No-Cache".
>
> When I run the webapp in IE7 / 8 the memory gradually increases.
> Leaving it overnight can get it close to 1Gb.
>
> Here is the client code:
>
> #################################################################
>
> public class LeakyApp implements EntryPoint
> {
>         public static final String IMAGE_SERVLET_NAME = "imageServlet";
>
>         public void onModuleLoad()
>         {
>                 leak();
>         }
>
>         private void leak()
>         {
>                 UrlBuilder urlBuilder = createUrlBuilder();
>
>                 final FlexTable table = new FlexTable();
>
>                 final List<Image> lstImages = createAndAddImages(5,10 ,table 
> );
>
>                 final String strURL = urlBuilder.buildString();
>
>                 final Timer timer = new Timer(){
>
>                         int nCounter = 0;
>
>                         @Override
>                         public void run()
>                         {
>                                 for (Image img : lstImages)
>                                 {
>                                         img.setUrl( strURL + "?" + 
> nCounter++) ;
>                                 }
>                         }
>                 };
>
>                 final Button btnStartLeak = new Button("Leak");
>                 btnStartLeak.addClickHandler( new ClickHandler()
>                 {
>                         @Override
>                         public void onClick(ClickEvent event)
>                         {
>                                 RootPanel.get().remove( btnStartLeak );
>                                 RootPanel.get().add( table );
>                                 timer.scheduleRepeating( 1000 );
>                         }
>                 });
>
>                 RootPanel.get().add( btnStartLeak );
>         }
>
>         private List<Image> createAndAddImages(int rowCount, int colCount,
> FlexTable table)
>         {
>                 List<Image> lstImages = new ArrayList<Image>();
>
>                 for(int row = 0; row<rowCount; row++)
>                 {
>                         for(int col = 0; col<colCount; col++)
>                         {
>                                 Image image = new Image();
>                                 lstImages.add( image );
>                                 table.setWidget(row, col, image);
>                         }
>                 }
>
>                 return lstImages;
>         }
>
>         private UrlBuilder createUrlBuilder()
>         {
>                 UrlBuilder urlBuilder = null;
>
>                 if( GWT.isScript() )
>         {
>                 urlBuilder = new UrlBuilder();
>             urlBuilder.setHost( Window.Location.getHost() );
>             urlBuilder.setPath( Window.Location.getPath() +
> IMAGE_SERVLET_NAME );
>         }
>         else
>         {
>                 urlBuilder = Window.Location.createUrlBuilder();
>             urlBuilder.setPath( IMAGE_SERVLET_NAME );
>         }
>
>                 return urlBuilder;
>         }
>
> }
>
> ############################################################
>
> Here is the servlet code:
>
> ############################################################
>
> public class ImageServlet extends HttpServlet
> {
>         private int nCounter = 0;
>         private Font font = new Font("Tahoma", Font.BOLD, 10);
>
>         private static Color getRandomColor()
>         {
>                 int r = (int)(Math.random()* 255);
>         int g = (int)(Math.random()* 255);
>         int b = (int)(Math.random()* 255);
>
>         return new Color(r,g,b);
>         }
>
>     @Override
>         protected void doGet ( HttpServletRequest request,
> HttpServletResponse response ) throws IOException
>     {
>
>         OutputStream out = response.getOutputStream();
>
>         response.setContentType("image/png");
>         response.addHeader("Pragma", "no-cache");
>         response.addHeader("Cache-Control", "no-cache");
>
>         ImageIO.write( generateRandomImage(), "png", out );
>
>         out.close();
>     }
>
>     private BufferedImage generateRandomImage()
>     {
>         return generateRandomImage(80, 80);
>     }
>
>     private BufferedImage generateRandomImage(int width, int height)
>     {
>         BufferedImage image = new BufferedImage(width, height,
> BufferedImage.TYPE_INT_ARGB);
>
>         Graphics2D g2d = image.createGraphics();
>         g2d.setFont( font );
>         g2d.setColor( getRandomColor() );
>         g2d.fillRect(0, 0, width, height);
>         g2d.setColor( Color.WHITE );
>         g2d.drawString("" + nCounter, 20, 20);
>
>         System.err.println(" img " + nCounter );
>
>         nCounter++;
>
>         if( nCounter == Integer.MAX_VALUE )
>                 nCounter = 0;
>
>         return image;
>     }
>
> }
>
> ############################################################
>
> Is there a programming error, or is it the nature of what the
> application is doing causing the memory leak? Can anyone explain what
> is happening behind the scenes?
>
> Thanks.

-- 
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-web-toolkit?hl=en.

Reply via email to