Cómo imprimir eventos de recolección de basura de la clase java?


9
 
java version "1.5.0_14" 
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_14-b03) 
Java HotSpot(TM) Server VM (build 1.5.0_14-b03, mixed mode) 

Estoy intentando depurar una NullPointerException que obtengo al pasar una referencia al campo estáticamente definido. Para ser más específico, estoy configurando un global en una instancia de memoria de trabajo Drools3.

workingMemory.setGlobal("log", workingMemorieslog); 

Mi suposición es que la clase en la que el campo está definido estáticamente se está recogiendo la basura. (La clase de recepción debe estar utilizando WeakReference o algo así, realmente no sé)

¿Cómo sugeriría depurar esto? Creo que si pudiera saber exactamente cuándo el GC de la JVM descarga una clase/instancia de una clase, podría limitar la causa del comportamiento erróneo. (Si no es la hora exacta del evento, al menos obtener una indicación de que algo sucedió).

Gracias, Maxim.

  0

Buena pregunta, buen seguimiento, buena respuesta por su cuenta. +1 a la pregunta y a la respuesta. 22 feb. 092009-02-22 20:00:14

10

Para rastrear la actividad de GC añadir esto a comando java:

-verbose: gc -XX: + PrintGCTimeStamps -XX: + PrintGCDetails

NPE que vas a encontrar es probable que pasando el valor nulo.

  0

Gracias por responder, Ya estoy corriendo con -XX: + PrintGCDetails -verbose: gc -Xnoclassgc y todavía no veo información de carga/descarga de clases. La única salida que veo son líneas como: [GC [PSYoungGen: 4096K-> 630K (4736K)] 4096K-> 790K (48064K), 0.0032750 segundos] 22 feb. 092009-02-22 00:27:12

  0

Como esta respuesta se ajusta mejor al tema inicial de la pregunta Lo estoy aceptando como respuesta. Gracias. 22 feb. 092009-02-22 16:31:10


0

¿Tiene la pila de seguimiento?

¿Ha intentado entrar en el método 'setGlobal' (suponiendo que tenga el código) para ver qué está pasando?


2

¿Por qué no mantener la clase en la memoria y luego ver si todavía sucede, si lo hace, entonces su problema está en otra parte. Si no, entonces sabes que el problema radica en la recolección de basura.


1

Resulta que el eclipse es el problema principal aquí.

voy a explicar:

he envuelto nuestra aplicación web en un método main() con el fin de probar el rendimiento. Usamos muchos códigos de terceros, a saber, el fondo común de Apache.

Resulta que teníamos varias versiones del tarro distribuidas en los proyectos (proyectos de eclipse). Mi aplicación que utiliza estos proyectos tenía commons-pool-1.3, un proyecto diferente tenía commons-pool-1.2.

Cuando se cargó utilizando el contenedor de servlets (Tomcat6), el cargador de clases de la webapp tenía prioridad, por lo que siempre cargó la versión de la aplicación web. Cuando comencé la aplicación usando main() eclipse en su comportamiento poco inteligente exportado, los proyectos dependientes entran en el classpath ANTES de los que están en el proyecto actual.

El conflicto se produjo entre 2 versiones de commons-pool, lo que provocó un comportamiento no definido. En un objeto, pedir prestado es SOMETIMES decidido a crear un nuevo objeto. No he buscado dentro del código de implementación, supongo que esto tiene que ver con un mapa estático retenido por GenericKeyedObjectPool (la clase problemática). Debido a que se creó una nueva instancia, de hecho contiene una referencia nula al mencionado global.

La solución a mi suerte fue bastante simple, el commons-pool está siendo utilizado solo por mi aplicación web para poder eliminarlo de todos los proyectos mencionados, de lo contrario creo que simplemente intentaría actualizarlos a una única versión.Si no pudiera hacerlo, realmente no sé qué habría hecho. Este es un predeterminado muy extraño de eclipse.

Gracias por leer y ayudar.

// ps. 3 días. Ese es el tiempo que dedico a comprender qué diablos hice mal en mi código de reemplazo de servlet. Resulta que ni siquiera soy el problema. : P

+1

FYI: Si tiene problemas de referencia de objetos extraños, intente iniciar sesión 'ProblemClass.class.getProtectionDomain(). GetCodeSource(). GetLocation(). ToExternalForm()' Esto devolverá el archivo jar o class desde el que se cargó la clase . Es un truco invaluable cuando se depuran aplicaciones web, que a menudo sufren problemas de cargadores de clases no deterministas. 02 ene. 132013-01-02 06:20:21