mi aplicación Java escrita consume demasiada memoria.Java consume demasiada memoria
Cómo funciona el programa: El usuario selecciona una fecha del calendario (GUI) y la aplicación carga datos en el componente JTable. Cada vez que se cargan datos, se crea y configura nuevo TableModel. No se crea ninguna JTable nueva, solo modelo.
¿Cuál es el problema?: cada nueva selección del día desde el calendario y cargando a JTable consume aproximadamente 2-3 MB de memoria. En la aplicación de inicio consume cca 50-60 MB de RAM, después de unos pocos "clics" en el calendario (como 20), la aplicación consume un tamaño de montón completo (128 MB). La aplicación se bloquea, por supuesto ...
¿Qué debo hacer?: Estoy bastante seguro de que las consultas de bases de datos están bien. De alguna manera podría establecer un tamaño de almacenamiento dinámico más grande (busqué en Google, pero esa sería la única solución para mi computadora, los usuarios no lo harían) O debería de alguna manera eliminar el viejo TableModel con datos de base de datos. ¿Pero no debería ser este el trabajo del recolector de basura? Puedo forzarlo (System.gc()) pero eso no ayuda ...
¡Gracias por cualquier consejo!
EDIT: código para manejar eventos de calendario (He eliminado Javadoc, que está en mi lengua materna)
package timesheet.handlers;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import org.jdesktop.swingx.JXMonthView;
import org.jdesktop.swingx.event.DateSelectionEvent;
import org.jdesktop.swingx.event.DateSelectionListener;
import timesheet.database.WorkerOperations;
import timesheet.frames.WorkerFrame;
import timesheet.logictrier.*;
public class WorkerMonthViewHandler {
private JXMonthView monthView;
private WorkerFrame workerFrame;
private WorkerOperations wops;
private Date[] week = new Date[5];
private WorkerTasksTableHandler wtth;
public WorkerMonthViewHandler(WorkerFrame workerFrame) {
this.workerFrame = workerFrame;
this.monthView = workerFrame.getWorkerMonthView();
wops = workerFrame.getWorkerOperations(); // for DB usage
}
public void initMonthView() {
List<Task> tasks = wops.getWorkerTasks(workerFrame.getWorker()); // db select
for (Task task : tasks) {
if (!monthView.getSelection().contains(task.getPlannedStart())) {
monthView.addFlaggedDates(task.getPlannedStart());
monthView.addFlaggedDates(task.gePlannedEnd()); // not really important
}
}
monthView.setSelectionDate(new Date());
monthView.getSelectionModel().addDateSelectionListener(new DateSelectionListener() {
public void valueChanged(DateSelectionEvent dse) {
Date d = monthView.getSelectionDate();
for (int i=0; i<week.length; i++) {
if (d.equals(week[i])) {
return;
}
}
Calendar cal = new GregorianCalendar();
cal.setTime(d);
long dayMs = 24 * 60 * 60 * 1000;
switch (cal.get(Calendar.DAY_OF_WEEK)) {
case(Calendar.MONDAY) : {
week[0] = new Date(cal.getTimeInMillis());
week[1] = new Date(cal.getTimeInMillis()+dayMs);
week[2] = new Date(cal.getTimeInMillis()+2*dayMs);
week[3] = new Date(cal.getTimeInMillis()+3*dayMs);
week[4] = new Date(cal.getTimeInMillis()+4*dayMs);
} break;
case (Calendar.TUESDAY) : {
week[0] = new Date(cal.getTimeInMillis()-dayMs);
week[1] = new Date(cal.getTimeInMillis());
week[2] = new Date(cal.getTimeInMillis()+1*dayMs);
week[3] = new Date(cal.getTimeInMillis()+2*dayMs);
week[4] = new Date(cal.getTimeInMillis()+3*dayMs);
} break;
case (Calendar.WEDNESDAY) : {
week[0] = new Date(cal.getTimeInMillis()-2*dayMs);
week[1] = new Date(cal.getTimeInMillis()-dayMs);
week[2] = new Date(cal.getTimeInMillis());
week[3] = new Date(cal.getTimeInMillis()+1*dayMs);
week[4] = new Date(cal.getTimeInMillis()+2*dayMs);
} break;
case (Calendar.THURSDAY) : {
week[0] = new Date(cal.getTimeInMillis()-3*dayMs);
week[1] = new Date(cal.getTimeInMillis()-2*dayMs);
week[2] = new Date(cal.getTimeInMillis()-1*dayMs);
week[3] = new Date(cal.getTimeInMillis());
week[4] = new Date(cal.getTimeInMillis()+1*dayMs);
} break;
case (Calendar.FRIDAY) : {
week[0] = new Date(cal.getTimeInMillis()-4*dayMs);
week[1] = new Date(cal.getTimeInMillis()-3*dayMs);
week[2] = new Date(cal.getTimeInMillis()-2*dayMs);
week[3] = new Date(cal.getTimeInMillis()-dayMs);
week[4] = new Date(cal.getTimeInMillis());
} break;
case (Calendar.SATURDAY) : {
week[0] = new Date(cal.getTimeInMillis()-5*dayMs);
week[1] = new Date(cal.getTimeInMillis()-4*dayMs);
week[2] = new Date(cal.getTimeInMillis()-3*dayMs);
week[3] = new Date(cal.getTimeInMillis()-2*dayMs);
week[4] = new Date(cal.getTimeInMillis()-dayMs);
} break;
case (Calendar.SUNDAY) : {
week[0] = new Date(cal.getTimeInMillis()-6*dayMs);
week[1] = new Date(cal.getTimeInMillis()-5*dayMs);
week[2] = new Date(cal.getTimeInMillis()-4*dayMs);
week[3] = new Date(cal.getTimeInMillis()-3*dayMs);
week[4] = new Date(cal.getTimeInMillis()-2*dayMs);
} break;
}
wtth = new WorkerTasksTableHandler(workerFrame,week);
wtth.createTable(); // sets model on JTable
}
});
}
public void reportTask() {
wtth.reportTasks(); // simple DB insert
}
}
Uso de NetBeans Profiler: Fecha de la toma: Dom 28 14:25:16 CET febrero 2010 del archivo: C: tamaño ... \ privado \ perfiles \ java_pid4708.hprof del archivo: 72,2 MB
Total bytes: 62 323 264
Total classes: 3 304
Total instances: 1 344 586
Classloaders: 18
GC roots: 2 860
Number of objects pending for finalization: 0
Podemos ver el código? – Fernando
Usted menciona un DB ... ¿puede decirnos más sobre lo que está haciendo, qué DB está utilizando, si está cerrando sus ResultSets, etc. ... parece ser un culpable mucho más probable. Además, ¿conserva alguna referencia a los viejos modelos? ¿Cuántos datos cargas en un modelo? ¿Su mesa tiene procesadores personalizados? – PSpeed
Nota: en el pasado he intercambiado JTable TableModels que contenía muchos miles de filas ... y nunca incrementé el tamaño del montón de forma predeterminada. Entonces algo más está en juego aquí. – PSpeed