style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Error al consultar imágenes de la Base de datos: java.lang.OutOfMemoryError: Java heap space

Saludo Cordial.

Estimados amigos de Java México, tengo la siguiente situación:

*En el módulo de inventario del software que estoy desarrollando, tengo que consultar los productos, y cada producto tiene 8 fotos; dichas fotos, las guardo previamente en la base de datos, usando campos tipo Blob.
El problema que tengo es que al realizar más de 3 o 4 consultas en dicho módulo, ya no me permite realizar ninguna otra adicional; es decir, ya no me muestra mas resultados y al revisar la consola de Windows me sale el error:

java.lang.OutOfMemoryError: Java heap space
at java.awt.image.DataBufferByte.(Unknown Source)
at java.awt.image.ComponentSampleModel.createDataBuffer(Unknown Source)....

(Adjunto imagen del Error)

He intentado aumentar la memoria heap de la máquina virtual, pero sólo me lo permite hasta 1GB y el equipo (PC) cuenta con 8GB de Memoria RAM y Sistema Operativo de 64 bits Windows 10.
Dentro del código también implemento el recolector de basura (con este último me permite por lo menos realizar un par de consultas más).

Espero me puedan colaborar con sus valiosos aportes y/o recomendaciones.

Saludos desde Colombia.

Bendiciones...

AdjuntoTamaño
Error.jpg63.87 KB

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 rodrigo salado anaya

Saca las imagenes

Te recomiendo que saques las imágenes de la BD y solo guardes las rutas para consumirlas. Pero hablando del escenario que tienes. ¿Haces un flush en cada petición?

no guardes la imagen en la bd

Yo tambien opino lo de rodrigo , que guardes las rutas de las imagenes y las consumas
Saludos

Saludos estimado rodrigo

Gracias por tu pronta respuesta, si he contemplado el guardar unicamente la ruta en la BD, lo que no me termina de convencer es que al tener las imagenes fuera de la BD es un poco riesgoso de que estas puedan ser eliminadas o sufran algún daño (pérdida) por fallas en el sitema operativo.
Con respecto a lo que me indicas del flush, me imagino que te refieres a aplicar el método flush en cada petición?

Para cada imagen que consulto en la base de datos uso estas líneas de código:
En la primera consulto los datos de la imagen y los almaceno en una variable Blob; luego, en un objeto tipo Image al cual he llamado imagenbd almaceno ya la información obtenida en la variable Blob pero en formato Image.
En la tercera línea lo que hago es almacenar el objeto Image en un registro de un array donde almaceno todos los datos consultados en la BD; y por último, al objeto Image le paso el método flush, el cual libera todos los recursos usados por el mismo (esto lo acabo de implementar y me falta probarlo en la máquina del cliente).

Blob blob1 = result.getBlob("foto1");
imagenbd= javax.imageio.ImageIO.read(blob1.getBinaryStream());
registros[j][21]= imagenbd;
imagenbd.flush();

Lo que me preocupa es que la consulta aún sigue siendo muy lenta, lo que me lleva a pensar que lo mejor es solo guardar la ruta en la BD.

Si tienes alguna recomendación adicional te lo agradecería.

Bendiciones...

Está raro que solo puedas

Está raro que solo puedas usar 1gb, ¿como estás poniendo ese valor? Con la opción -Xmx y -Xms ?

Revisa la definición de las imágenes que estás guardando y asegurate de guardarlas con un tamaño óptimo (hay imágenes que en formato bmp miden varios megabytes y en formato jpg solo un par de kb )

También revisa que está haciendo tu programa para mostrar las imágenes, quizá estás cargando toda la base de datos en memoria y obvio se le va a acabar el espacio, un usuario quizá pueda / quiera ver de 20 a 50 productos por página, lo cual serían 400 imágenes máximo por página ( suponiendo que cargas las 8 imágenes por producto ), si cada imagen fuera enorme y midiera 100kb tendrías cuando mucho 40 mb de memoria usada lo cual deja mucho espacio.

Finalmente revisa que haces con las imágenes ( y los objetos ) después de que ya no los usas, quizá se están quedando en memoria y jamás te deshaces de ellas.

Imagen de Nopalin

Crea un ImageIcon con un archivo local

Yo estoy en desacuerdo que mis compañeros, es una excelente opción guardar los binarios en la base de datos y más que como dices, es mucho más fácil hacer respaldos y restaurar.

Ahora, realmente no se que haga tu método, pero yo he trabajado con archivos y lo que hago es lo siguiente: tengo un cache local de todas las imagenes que el usuario ha consultado, cuando el usuario quiere ver una, primero busco en el cache y si no existe voy por ella a la bd, la guardo en el cache y luego la muestro. De esta manera minimizo el tráfico y consultas a la bd. Si por alguna razón el cache se pierde, bueno solo se vuelve a traer y listo.

La pregunta es, estas realizando alguna operación con esa imagen? yo opino que no te la compliques y hagas un ImageIcon con el archivo del cache y luego se la asignes a un JLabel, que estará en un JPanel y listo.

Saludos

Segun un estudio de....

Se que el nombre de Microsoft no es muy bien recibido pero en su departamento de investigacion hicieron un pequeño estudio sobre este tema:
...
objects smaller than 256K are best stored in a database while objects larger than 1M are best stored in the filesystem. Between 256K and 1M, the read:write ratio and rate of object overwrite or replacement are important factors...

y aqui les dejo el link al paper Estudio de Microsoft sobre almacenar imagenes en bd

Saludos estimado OscarRyz

*Efectivamene el valor lo coloco usando la opción -Xmx y -Xms.
*Todas las imágenes las estoy guardando en formato .jpg
*Actualmente estoy haciendo pruebas con solo 10 registros; es decir, para un total de 80 imágenes en total y aún así me sale el error de Java Heap Space.
*Lo que hago una vez que ya no uso las imágenes es emplear el método flush(); y el recolector de basura.
*Las imagenes que el usuario carga son de 1600 x 1200, para un peso promedio de 220 kb por imagen.
*He tratado de almacenar las imagenes en un tamaño menor, pero se pixelan demasiado.

Agradezco tus valiosos aportes, cualquier otra recomendación es bienvenida.

Bendiciones...

Con -Xmx deberías de poder

Con -Xmx deberías de poder usar más de un 1gb fácilmente.

220 kb promedio x 80 imágenes tienes un total de 17mb de memoria usada, muy por debajo de los 1024 que tienes disponibles.

Ahora tienes que ver como estás usando la memoria de tu aplicación. De nada sirve llamar al método flush y al recolector de basura si los objetos no pueden ser eliminados ( si aún los estás usando ), por ejemplo si los agregas a un arreglo y jamás los sacas el recolector "piensa" que aún los estás usando (porque en realidad aún los estás usando) y no libera esa memoria. Ni siquiera tienes que sacarlos uno por uno del arreglo, basta con que elimines la referencia al arreglo para que todo lo que esté adentro pueda ser liberado ( si es que no existe ninguna referencia a él en algún otro lado )

Esta es una webapp o una aplicación de escritorio con Swing?

Intenta usando el profiler que viene con Java ( ejecuta el comando jvisualvm ) y puedes ver como se está usando la memoria en tu aplicación.

Saludo estimado OscarRyz

Estoy trabajando con una aplicación de Escritorio con Swing, en realidad tengo un metodo donde consulto las imagenes, el cual me devuelve un arreglo, y a dicho metodo lo llamo desde otra clase y almaceno los resultados en un nuevo arreglo para seguidamente asignar las imagenes en los paneles respectivos.

Saludo estimado Nopalin

Qué código usas para consultar tus imagenes en la BD?, yo lo hago de la siguiente forma:

Blob blob4 = result.getBlob("foto4");
imagenbd= ImageIO.read(blob4.getBinaryStream()); // donde imagenbd es una variable tipo private Image
registros[j][19]= imagenbd;

en la segunda línea es donde me está consumiendo bastante recursos, qué me sugieres?

De antemano te agradezco tu valiosa colaboración.

Bendiciones...

Imagen de Nopalin

Pon algo de código, para

Pon algo de código, para saber exactamente como estas trabajando.

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">