Ayuda con java.lang.OutOfMemoryError

Hola les cuento que me encargaron solucionar un Bug en una aplicacion en java con jsp, en donde debo obtener unos datos de la DB y exportarlos a excel, cuando lo hago con pocos datos va muy bien, pero cuando lo hago con mas cantidad me aparece el siguiente error:

0000004a SystemErr R java.lang.OutOfMemoryError
at java.net.ServerSocket.accept(ServerSocket.java(Compiled Code))

este es un fragmento de codigo

 

alguien me comento que es un problema de memoria de JVM que se soluciona aumentando, el problema es que eso no lo podre hacer en el servidor de producción, ¿Que es lo que puedo hacer?

gracias

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

entiende

Lo primero es entender que la memoria no es infinita. Y con eso en mente, optimizar tu código para que use poca memoria.

Ese código que pones no es necesariamente la causa del problema. Supongo que lees registros de base de datos y los metes en un excel que devuelves en la respuesta. Tal vez tu proceso es así:

1. Leer todos los registros que vas a meter al excel
2. Crear el excel
3. Meter todos los registros
4. Convertir el excel a un arreglo de bytes
5. Aventar eso a la respuesta.

Una manera de usar menos memoria es crear el excel, y luego en un ciclo leer del ResultSet resultante de la consulta a base de datos, y meterlo al excel. La JVM se encargará de ir liberando memoria. Y busca si el objeto que representa tu excel tiene algún método para escribirse directamente a un stream (es muy probable que sí); de ser así pues lo mandas a escribirse directo a la respuesta sin convertirlo en arreglo de bytes.

Lo menos que puedes hacer, de entrada, para usar LA MITAD de la memoria que estás usando actualmente, es NO INVOCAR dos veces  ; invócalo una sola vez y guárdalo en una variable, para que tengas la longitud y además lo puedas escribir. No sabes cómo está implementado ese método y tal vez no hace cache del resultado sino que cada vez que lo invocas utiliza un montón de memoria y por eso se te acaba.

Y tal vez hagas lo anterior y vas a decir "oh gracias eso resuelve el problema", pero no es cierto. Sólo resolvió el problema CON LOS DATOS ACTUALES. Cuando alguien genere un excel con más datos puede quedarse la JVM sin memoria. Sobre todo considerando que es una aplicación multiusuario y seguramente te acabas la memoria ahorita tú solo, es decir un solo usuario. Imagina que 10 usuarios generan ese reporte, seguro se terminan la memoria.

Incluso habría que ver si puedes ir escribiendo lo que se genera del excel directo al stream de salida. O si el objeto no tiene un método para escribirse a un stream (que se me haría muy raro), pues si hay un método para escribirse a un archivo, entonces lo escribes a un archivo temporal y luego vas leyendo de ese archivo y escribiendo al stream de respuesta, con un buffer pequeño (digamos 64KB o algo así).

Lo revisare

Hola Ezamudio

Pues revisare lo que me comentas.

he revisado y es un archivo de aprox 135520 registros lo verifique directo en la base y tarda un poco creo que por esa razón tarda también en java, buscando en Internet dice que una posible solución seria modificar los -XmsXXXXm -XmxXXXm, pero según lo que me dices no se si sea correcto hacerlo o debería tomar en cuenta la opción de recrear el proceso de como se crea el excel.

gracias

Imagen de Shadonwk

que ondita loko!! Zamudio ya

que ondita loko!!

Zamudio ya te dio la solución, realmente necesitas optimizar tu código y coincido con él en que la memoria se esta acabando en hacer la lectura de los datos desde la base y meterlos al excel igual otra fuga de memoria pueden ser tus querys necesitarías revisarlas y optimizarlas un punto que tienes que tomar en cuenta muy seriamente es lo que dice Enrique "la memoria no es infinita" ahora bien cambiar los parámetros de la jvm ciertamente ayuda pero no es la solución al problema revisa bien tu código o en su defecto por en fragmento correo y tal vez podamos echarte una mano.

Solucionado

Gracias.

estuve revisando el código y modifique algunas cosillas y listo anduvo sin necesidad de aumentar memoria a la jvm.

saludos