title: Memory usage of a GWT application
body: <p>I'm currently working on a GWT application as a proof of technology for future projects. I like the way of building my AJAX code in Java instead of JavaScript. But I seem to be running into a memory problem when I repeat calls to an RPC service. The browser memory usage keeps growing and growing. </p>
  
  <p>When searching Google I keep reading about how great GWT is and that its impossible to get memory leaks so can anyone explain why my browser (Firefox and Chromium) memory is rocketing?</p>
  
  <p>Thanks in advance for helping me,
  Bram</p>
  
  <p>The code:</p>
  
  <pre><code>...
  
  class ExampleTable extends Composite
  
    private RPCService rpcService;
    private Timer tableUpdater;
  
    public ExampleTable(){
     ... Init timer and RPC Service
     ... Add components
     initWidget();
    }
  
    private void getTableDataFromRPCService() {
    this.rpcService.getData(new AsyncCallback&lt;ArrayList&lt;Data&gt;&gt;() {
  
        @Override
        public void onSuccess(ArrayList&lt;Data&gt; result) {
            ExampleTable.this.updateTable(result);
        }
  
        @Override
        public void onFailure(Throwable caught) {
            //Do nothing
        }
    });
    }
  
    private void updateTable(ArrayList&lt;Data&gt; tableData){
      ... Update the table
    }
  
    private void startUpdateTask() {
        this.serviceUpdater = new Timer() {
            @Override
            public void run() {
              ExampleTable.this.getTableDataFromRPCService();
            }
        };
        serviceUpdater.scheduleRepeating(2000);
    }
  }
  </code></pre>
  
  <p><strong>EDIT:</strong></p>
  
  <p>I've spent some time to write a test application which can be downloaded <a href="http://www.pouwelse.com/GWTMemoryIssue.zip" rel="nofollow noreferrer">here</a>. I ran the application for about half an hour with the table update enabled after that Firefox took about 350MB of memory. I also ran the test with the update table disabled for an hour memory usage in Firefox went to little over 100MB.</p>
  
  <p>(To run this sample you need the Google visualization API for GWT which can be downloaded from Google but I'm not allowed to post the link because of a new user policy )</p>
  
  <p>I just got home from work and start another test without the table  data update to see if memory usage keeps increasing or if it stops at a certain point.</p>
  
  <p>This is the client implementation class (GWTMemoryIssue.java):</p>
  
  <pre><code>public class GWTMemoryIssue implements EntryPoint {
  //Run with or without table
  private static final boolean WITH_TABLE = false; 
  
  private final TestServiceAsync rpcService = GWT.create(TestService.class);
  
  private Panel panel;
  private Timer timer;
  private Table table;
  
  public void onModuleLoad() {
      RootPanel rootPanel = RootPanel.get();
  
      this.panel = new VerticalPanel();
      this.panel.setSize("100%", "100%");
  
      rootPanel.add(panel);
  
      if (WITH_TABLE) {
          loadTable();
      }else{
          startUpdateTask();
      }
  
  }
  
  private void startUpdateTask() {
      this.timer = new Timer() {
  
          @Override
          public void run() {
              GWTMemoryIssue.this.getTableData();
  
          }
      };
      this.timer.scheduleRepeating(2000);
  }
  
  public void loadTable() {
      Runnable onLoadCallback = new Runnable() {
          public void run() {
              GWTMemoryIssue.this.table = new Table(createTableData(), createTableOptions());
              GWTMemoryIssue.this.table.setSize("100%", "100%");
              GWTMemoryIssue.this.panel.add(GWTMemoryIssue.this.table);
              GWTMemoryIssue.this.startUpdateTask();
          }
      };
  
      VisualizationUtils.loadVisualizationApi(onLoadCallback, Table.PACKAGE);
  }
  
  private Options createTableOptions() {
      Options options = Options.create();
  
      return options;
  }
  
  private DataTable createTableData() {
      DataTable data = DataTable.create();
  
      data.addColumn(ColumnType.STRING, "Name");
      data.addColumn(ColumnType.NUMBER, "Intval 1");
      data.addColumn(ColumnType.NUMBER, "Intval 2");
      data.addColumn(ColumnType.NUMBER, "Intval 3");
  
      return data;
  }
  
  private void getTableData() {
      rpcService.getListOfItems(new AsyncCallback&lt;ArrayList&lt;ListItem&gt;&gt;(){
          public void onFailure(Throwable caught) {
              // Do nothing
          }
  
          public void onSuccess(ArrayList&lt;ListItem&gt; result) {
              if (WITH_TABLE){
                  GWTMemoryIssue.this.updateTableData(result);
              }else{
                  //Ignore the data from the server
              }
          }
      });
  }
  
  private void updateTableData(ArrayList&lt;ListItem&gt; result) {
      DataTable data = createTableData();
  
      data.addRows(result.size());
  
      int row = 0;
      for (ListItem li : result) {
          data.setValue(row, 0, li.getName());
          data.setValue(row, 1, li.getIntVal());
          data.setValue(row, 2, li.getIntSecondVal());
          data.setValue(row, 3, li.getThirdIntVal());
          row++;
      }
  
      this.table.draw(data, createTableOptions());
  }
  }
  </code></pre>