9

Una de las pérdidas de memoria que he descubierto en nuestra aplicación es el campo estático privado java.awt.Window.allWindows, que realiza un seguimiento de cada ventana instanciada. Tenemos cuadros de diálogo que se crean, usan y luego se olvidan, y se esperaba que desaparecieran y se recogieran basura. Este campo privado los mantiene en el alcance, indefinidamente, hasta que se les llame al método dispose(). Y, por definición, no podemos hacer eso cuando se salieron del alcance.¿Por qué debería tener que deshacerse de() una ventana java.awt.Window que sale del alcance?

No entiendo por qué esto está diseñado de esta manera. Parece contrario al espíritu de la recolección de basura tener que dejar explícitamente al sistema saber cuando haya terminado con un objeto de ventana. Obviamente ya terminé, ya que está fuera de mi alcance.

Entiendo lo que hace el método dispose(): deshacerse de los objetos similares del sistema. Entiendo que esto está fuera de Java y que necesita alguna forma de hacerlo y que Swing no debería simplemente perder la pista de esos objetos, o de lo contrario tendría una pérdida de memoria. Pero, ¿qué se logra manteniendo una referencia a mi Ventana para siempre, cuando nunca más voy a usarlo?

¿Alguien puede explicar por qué es necesario?

+0

Cuando se llama a 'removeNotify', la' Ventana' se eliminará de 'allWindows'. 'Las ventanas' contienen recursos nativos, por lo que deben eliminarse de la misma manera que si fuera una conexión de base de datos. –

+0

Tenía la impresión de que cuando las conexiones de mi base de datos quedan fuera del alcance, se cierran automáticamente.Probablemente estoy equivocado acerca de eso. :) Sin embargo, hoy en día, todo lo que un servidor me administra, a excepción de los programas cortos. – skiphoppy

Respuesta

14

Odio decirlo, pero así es como funciona una GUI.

Las ventanas no tienen bloqueos. Lo que significa que una vez que creas uno en el código, tu código continúa ejecutándose.

Esto significa que su ventana probablemente se salga de alcance inmediatamente después de la creación, a menos que haya almacenado explícitamente una referencia en otro lugar. La ventana todavía está en pantalla en este punto.

Esto también significa que necesita alguna otra forma de deshacerse de él cuando haya terminado con él. Ingrese el método Window dispose(), que se puede llamar desde uno de los oyentes de la ventana.

+1

D'oh! ¡Lo entiendo! Las personas crean ventanas todo el tiempo a las que no mantienen referencias, pero las ventanas aún son visibles y se están ejecutando. Simplemente no estaba pensando en eso porque en esta situación estamos usando la ventana de inmediato y luego la hacemos invisible, y luego la olvidamos (queda fuera del alcance). Ahora veo por qué este es el valor predeterminado para Windows. Sabía que había un caso de uso racional en alguna parte. :) – skiphoppy

+0

Oh, correcto, debería haber señalado que la ventana todavía estaba en la pantalla cuando su variable salió del alcance. Voy a editar eso en mi respuesta solo en caso de que alguien se pierda eso. – Powerlord

2

Esto podría explicar que: AWT Threading Issues

Simplemente, hay mucho más en juego en la JVM que sólo los componentes visibles, con hilos de fondo y así sucesivamente. Estos subprocesos y otros recursos se mantienen hasta que se eliminó la última Ventana en la JVM, luego de lo cual se ordenan y la JVM puede salir limpiamente. Por lo tanto, cada ventana, marco y ventana de diálogo que utilice esencialmente mantiene un bloqueo en la JVM para evitar que se cierre, y usted tiene que administrarlo manualmente con llamadas al dispose().

Estoy de acuerdo que es un poco molesto. Me he topado con esto algunas veces yo mismo.

1

En Java cuando tiene código nativo (que es lo que los pares de estos componentes de Windows), necesita mantener una referencia para evitar que el recolector de basura intente recolectar el objeto mientras los punteros nativos todavía están alrededor, que causaría todo tipo de cosas malas (bloqueos de máquina virtual, etc.).

Véase, por ejemplo, la discusión here.

1

El método dispose() destruye el objeto del objeto WindowEvent. No mata la aplicación/p

Cuestiones relacionadas