2010-06-05 11 views
6

Tengo un problema con alguna API de framework que llama al método BufferedImage.getGraphics() y causa la pérdida de memoria. Lo que hace este método es que siempre llama a BufferedImage.createGraphics(). En una máquina de Windows, createGraphics() es manejado por Win32GraphicsEnvironment que mantiene una lista de listeners dentro de su campo displayChanger. Cuando llamo getGraphics en mi BufferedImage someChart, se añade someChart 's SurfaceManager (que conserva una referencia a someChart) a los oyentes mapa en Win32GraphicsEnvironment, evitando someChart ser basura recogida. Nada después elimina algunaCarta's SurfaceManager del listeners map.BufferedImage.getGraphics() dando como resultado la pérdida de memoria, ¿hay alguna solución?

En general, la trayectoria se resume la detención de un BufferedImage de ser basura recogida, una vez getGraphics se le llama, es el siguiente:

GC raíz -> localGraphicsEnvironment (Win32GraphicsEnvironment) -> displayChanger (SunDisplayChanger) -> oyentes (mapa) ->clave (D3DChachingSurfaceManager) -> bImg (BufferedImage)

que podría haber cambiado el código del marco de modo que después de cada llamada a BufferedImage.getGraphics(), que mantiene una referencia a SurfaceManager del BufferedImage. Luego, obtengo localGraphicsEnvironment, lo transfiero a Win32GraphicsEnvironment, luego llamo removeDisplayChangedListener() usando la referencia al SurfaceManager de BufferedImage. Pero no creo que esta sea una forma adecuada de resolver el problema.

¿Podría alguien ayudarme con este problema? ¡Muchas gracias!


Información adicional y RESULTADOS

El componente que estoy tratando de agregar a la interfaz de usuario es hace llamadas a BufferedImage.getGraphics() cada vez que se volvió a pintar. Como resultado, la cantidad de basura guardada por displayChanger (dentro de SunGraphicsEnvironment) debería crecer a medida que el componente se vuelve a pintar.

Sin embargo, las cosas un comportarse extrañamente suficiente:

cuando conté mis acciones en mi interfaz de usuario que seguramente daría lugar a pintar, a continuación, compruebe el número de oyentes de basura en el interior displayChanger contra mi cuenta, no coinciden arriba. (Por ejemplo, hubo 8 oyentes antes de mis clics, e hice 60 clics. Después de todo, solo hay 18 oyentes.)

Por otro lado, si enciendo el punto de interrupción, y paso al proceso de agregar cosas para displayListeners, cada clic individual resultó en una nueva entrada en displayListeners. Y así, cada imagen almacenada en búfer en displayListeners se convierte en basura.

Consideré que la posibilidad de SurfaceManager, que se utiliza como la clave para displayListeners, puede compartirse o reutilizarse, pero mi experimento descartó esta posibilidad. También consideré el almacenamiento en caché y evité deliberadamente el almacenamiento en caché haciendo que cada llamada para pintar sea única.Aún así, no tengo ni idea de cómo podría suceder esto y cómo resolver la fuga.

Respuesta

1

Intente llamar al flush() cuando ya no necesite su imagen.

+0

Lo intenté, pero no funcionó. – Huinan

7

Después de representar el BufferedImage, debe invocar dispose() en el contexto de gráficos devuelto por createGraphics(). Aquí hay un example y un list de métodos similares.

Addendum: Esto parece una fuga de objeto llamada packratting; la falta de coincidencia del oyente suena como un artefacto de usar el depurador. Puede obtener algunas ideas del artículo Plugging memory leaks with soft references, por Brian Goetz.

+0

Lo siento, no mencioné que se llamó al método dispose(), pero no libera la imagen porque todavía se conserva una referencia mediante displayChanger. Incluso traté de obtener el administrador de superficie de la imagen y llamar a flush() con la esperanza de destruir el administrador. No funcionó. – Huinan

+0

@ user359202: Me pregunto acerca del caché de fuente en 'SunGraphicsEnvironment'; He elaborado más arriba. – trashgod

+0

Suena realmente cerca. ¿Podría elaborar más sobre la memoria caché de fuentes en SunGraphicsEnvironment y cómo esto puede estar relacionado con mi problema? Hay poca información disponible sobre esta parte de Java que pude encontrar. – Huinan

Cuestiones relacionadas