GWT 应用程序的内存使用情况

2024-04-06

我目前正在开发 GWT 应用程序,作为未来项目的技术证明。我喜欢用 Java 而不是 JavaScript 构建 AJAX 代码的方式。但当我重复调用 RPC 服务时,我似乎遇到了内存问题。浏览器内存使用量不断增长。

当我搜索 Google 时,我一直在读到 GWT 有多棒,而且它不可能出现内存泄漏,所以有人能解释一下为什么我的浏览器(Firefox 和 Chromium)内存猛增吗?

预先感谢您对我的帮助, 布拉姆

代码:

...

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<ArrayList<Data>>() {

      @Override
      public void onSuccess(ArrayList<Data> result) {
          ExampleTable.this.updateTable(result);
      }

      @Override
      public void onFailure(Throwable caught) {
          //Do nothing
      }
  });
  }

  private void updateTable(ArrayList<Data> tableData){
    ... Update the table
  }

  private void startUpdateTask() {
      this.serviceUpdater = new Timer() {
          @Override
          public void run() {
            ExampleTable.this.getTableDataFromRPCService();
          }
      };
      serviceUpdater.scheduleRepeating(2000);
  }
}

EDIT:

我花了一些时间编写了一个可以下载的测试应用程序here http://www.pouwelse.com/GWTMemoryIssue.zip。在 Firefox 占用了大约 350MB 内存之后,我在启用表更新的情况下运行了该应用程序大约半个小时。我还在禁用更新表的情况下运行了测试,一个小时后 Firefox 的内存使用量略高于 100MB。

(要运行此示例,您需要 GWT 的 Google 可视化 API,可以从 Google 下载该 API,但由于新的用户政策,我不允许发布链接)

我刚刚下班回家,在没有表数据更新的情况下开始另一个测试,看看内存使用量是否持续增加或者是否在某个点停止。

这是客户端实现类(GWTMemoryIssue.java):

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<ArrayList<ListItem>>(){
        public void onFailure(Throwable caught) {
            // Do nothing
        }

        public void onSuccess(ArrayList<ListItem> result) {
            if (WITH_TABLE){
                GWTMemoryIssue.this.updateTableData(result);
            }else{
                //Ignore the data from the server
            }
        }
    });
}

private void updateTableData(ArrayList<ListItem> 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());
}
}

您在此处提供的所有附加信息是一些想法。我猜想内存增加是由内存中剩余的列表引起的。内存可能根本没有被释放,或者 JavaScript 垃圾收集器没有时间进行清理,因为更新之间的时间间隔很短。您可以执行以下一些测试:

  1. 要测试垃圾收集器是否没有时间调整代码,以便更新仅运行有限次数,然后检查内存使用量是否在几分钟内减少。如果内存使用量减少,那么在现实世界的示例中,这可能不是一个问题。但通过将延迟设置为 30 秒来简单测试一下。
  2. 您可以通过在使用后清除列表来帮助垃圾收集器:我不知道什么最有效,所以这里有一些建议:从列表中删除对象,或循环列表并将值设置为 null。在正常情况下这应该是不必要的,因为垃圾收集器会这样做。

您还可以尝试以下 Firefox 内存分析器插件,看看是否可以找到内存增加的位置:http://ajaxian.com/archives/enhanced-firefox-memory-profiler-add-on http://ajaxian.com/archives/enhanced-firefox-memory-profiler-add-on

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GWT 应用程序的内存使用情况 的相关文章

随机推荐