2010-08-11 10 views
6

Tengo una aplicación de navegador Swing con un error que al agregar/eliminar a/desde la GUI la memoria no se libera para esos objetos y estoy tratando de rastrear lo que los contiene. El problema es que no sé cómo decir cuándo algo se ha liberado completamente de la memoria.¿Cómo saber cuándo se libera la memoria de un objeto Java?

¿Hay alguna manera de saber si un objeto se ha liberado de la memoria? Estoy acostumbrado a Objective-C, donde hay varias maneras de decirlo.

Gracias

+0

(FWIW, por lo general es un oyente) –

+0

Pensé que podría ser, pero traté de eliminar todos los ActionListeners y componentListeners – Shizam

Respuesta

6

Realmente no se puede hacer en Java. Todas las respuestas que mencionan los finalizadores no son realmente lo que buscas.

Lo mejor que puede hacer es poner en cola una Referencia Phantom en una consulta de Referencia y encuesta hasta que obtenga la referencia.

final ReferenceQueue rq = new ReferenceQueue(); 
final PhantomReference phantom = new PhantomReference(referenceToObjectYouWantToTrack, rq); 

¿Quieres leer la respuesta de Pedro Kofler aquí (se explica lo que es un PhantomReference es):

Have you ever used Phantom reference in any project?

muy interesante leer aquí:

http://www.kdgregory.com/index.php?page=java.refobj

Básicamente, estoy usando una referencia fantasma en un proyecto donde un tipo de caché muy especial necesita ser computado una vez, cuando el el software está instalado. Para calcular de manera eficiente esta memoria caché (basada en disco), se necesita una gran cantidad de memoria (cuanto más, mejor). Estoy usando PhantomReference para rastrear "casi exactamente" cuando se libera esa cantidad gigantesca de memoria.

+0

Buena información y enlaces, parece que Peter sugiere usar un generador de perfiles. – Shizam

+0

Dado que no hay ningún problema que los finalizadores puedan resolver que PhantomReferences no pueda, actualicé mi respuesta. Creo que los finalizadores son "lo suficientemente buenos" para lo que OP intenta hacer, pero me doy cuenta de que no debería alentar las técnicas semidegradadas. –

+0

Hasta ahora, los perfiladores que probé no tienen la resolución para mostrar si se lanza un único objeto. Parece que esta respuesta (PhantomReferences) puede ser la mejor herramienta, pero tengo dificultades para encontrar un ejemplo de cómo usarla solo para rastrear objetos publicados. El ejemplo en kdgregory lo está usando para rastrear conexiones SQL. ¿Qué es exactamente lo que estoy sondeando para valores nulos, la referenceQueue o alguna otra lista de seguimiento? – Shizam

3

Editar:

Como NoozNooz42 ha señalado, un PhantomReference puede hacer todo un finalizador puede, sin los problemas presentes finalizadores. Por lo tanto, recomiendo usar PhantomReferences en la extensión finalize(). Mantengo mi publicación original intacta, ya que creo que los programadores de Java deberían saber al menos que finalize() existe.

Post original:

Cada clase de Java tiene un método finalize() que se ejecute cuando no hay otros objetos tienen una referencia a esa clase. Se puede extender este método así:

protected void finalize() throws Throwable { 
    try { 
     // Do whatever you want 
    } finally { 
     super.finalize(); 
    } 
} 

De esta manera, se puede averiguar si algo contiene una referencia a los objetos en cuestión. Solo asegúrese de llamar siempre al super.finalize() si usa este enfoque.

de referencia sobre la finalización:

http://java.sun.com/developer/technicalArticles/javase/finalization/

+2

Finalizadores deben evitarse en Java porque no dan garantía cuando los objetos realmente se recogen. También finalice solo funciona cuando la instancia es elegible para la recopilación. Los objetos problemáticos normalmente se guardan en la memoria en alguna otra instancia, por lo que la finalización no ayuda. Vea también aquí: http://my.safaribooksonline.com/0201310058/ch02lev1sec6 (Java efectivo por Josh Bloch) –

+0

@jwachter: Buen punto, pero su enlace requiere iniciar sesión para leer. –

+0

@Justin Ardini: la finalización ocurre ** MANERA ANTERIOR ** un objeto está GC'ed. Ver mi respuesta: el OP está después de PhantomReference, no finalizadores. – NoozNooz42

1

Trate YourKit. Es un generador de perfiles de Java que puede mostrarle el uso de su memoria y qué diablos está pasando. IIRC, la versión de prueba gratuita puede integrarse con Eclipse y tiene todas las funciones de la versión paga (solo tiene un límite de tiempo).

3

Existen múltiples formas de detectar fugas de memoria. Aquí los tres Actualmente estoy pensando en:

  1. Colocación de un analizador para su aplicación (o NetbeansEclipse TPTP deberían ser útiles aquí)
  2. Hacer un volcado del montón y analizar (con Eclipse Memory Analyzer) lo instancias de una clase son celebrada en la memoria por la cual otras instancias.
  3. Adjuntar VisualVM para rastrear el estado de recolección de basura.
+0

pero la pregunta no mencionaba ninguna ** pérdida de memoria **. El OP solo quiere rastrear cuando un objeto tiene GC. – NoozNooz42

+0

Desafortunadamente el # 1 nunca funcionó para mi applet, nunca entendí por qué. Verificará también VisualVM, actualmente estoy probando YourKit. – Shizam

+0

@ NoozNooz42 tienes razón. Pero creo que normalmente solo buscas cuando se recopila algo si hay un problema de memoria. –

Cuestiones relacionadas