В настоящее время я работаю над приложением GWT в качестве доказательства технологии для будущих проектов. Мне нравится способ построения моего кода AJAX на Java вместо JavaScript. Но я, кажется, сталкиваюсь с проблемой памяти, когда я повторяю вызовы службы 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:
Я потратил некоторое время, чтобы написать тестовое приложение, которое можно загрузить здесь . Я запустил приложение около получаса с включенным обновлением таблицы, после чего Firefox занял около 350 МБ памяти. Я также запустил тест с отключенной таблицей обновлений, поскольку использование Firefox в течение часа занимало чуть более 100 МБ.
(Для запуска этого примера вам понадобится API визуализации Google для GWT, который можно загрузить с Google, но я не могу опубликовать ссылку из-за новой политики пользователя)
Я только что вернулся с работы и начал другой тест без обновления данных таблицы, чтобы посмотреть, продолжает ли увеличиваться использование памяти или он останавливается в определенный момент.
Это класс реализации клиента (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());
}
}