2012-02-28 18 views
5

Por "liberado" quiero decir que no hay referencias para el cargador de clases restante.¿Cuándo se llama a finalize en singletons cuando se lanza un cargador de clases?

Nos encontramos con un problema en el que una aplicación Java EE que se redistribuye con frecuencia consume espacio permgen. El análisis muestra que un singleton en la aplicación Java EE ha pasado las referencias a los objetos de la aplicación-cargador de clases fuera de la aplicación (en violación de las reglas de Java EE) y no las borra cuando la aplicación no se implementa.

Suponiendo que no quedan otras referencias al singleton o al objeto de clase, ¿se llamará a finalize() de singleton cuando se libere el cargador de clase de su clase? Me gustaría borrar las referencias deshonestas allí. ¿O estoy en un catch-22 donde finalizar no se llamará hasta que el cargador de clases en sí mismo pueda ser recogido basura, y por lo tanto nunca será llamado debido a las referencias externas deshonestas?

La cuestión principal aquí es quizás:

¿Un objeto de la clase será recogido de basura, en este caso en su cargador de clases no puede ser todavía? Esto puede depender de la especificación del comportamiento del cargador de clases, o puede depender de la implementación.

Referencias (¡el otro tipo! ;-)) serían apreciadas, pero no son necesarias.

+0

Si pasa referencias de cargadores de clases considere el uso de WeakReference (s) y WeakHashMap en lugar de referencias fuertes (regulares). – Stefan

Respuesta

4

Una clase con una referencia estática, será elegible solo para la recolección de basura, si el cargador de clase es elegible para GCing y no hay otras referencias a él.

Una clase o interfaz puede descargarse si y solo si el recolector de basura puede reclamar su cargador de clase definidora.

http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.7

Además, cada clase tiene una referencia a su cargador de clases. Por lo tanto, un cargador de clases no es elegible para GCing siempre que haya referencias a clases cargadas por él u objetos de esas clases de un objeto no coleccionable.

El finalizador se ejecuta un tiempo después de que un objeto sea elegible para la recolección de basura y antes de que se lleve a cabo el GC.

La aproximación a las referencias entrantes gratuitas, que previenen el GCing, en un finalizador no funciona. No se llamará al finalizador mientras existan tales referencias porque impiden que el objeto sea elegible para la recolección de basura.Por ejemplo no se puede romper esta cadena de referencia desde el interior:

singleton instance <--- singleton class <--- class loader <-- 
<-- any class loaded by that class loader <-- any object of such a class 
<-- object loaded by another classloader referencing such an object or class 
+0

Las referencias no son al singleton (directa o indirectamente), por lo que el bucle de referencia no es un problema. Lo principal que trato de entender es si la clase puede ser GC aunque haya referencias externas sobresalientes a otras clases de este cargador de clases publicado. –

+0

¿Qué quiere decir con "liberado". Un cargador de clases solo es elegible para GCing, si todas las clases cargadas por él también son elegibles para GCing ya que cada clase tiene una referencia a su cargador de clases. –

+0

Ok, y ClassLoader tiene un vector de todas las clases que ha cargado ... por lo que el finalizador no funcionará independientemente. ¡Muchas gracias! –

0

El comportamiento de los finalizadores no ha cambiado el cargador de clases o el uso de perm gen, aunque sí empeora el rendimiento. Los objetos no pueden ser recolectados hasta después de ejecutar el finalizador. Entonces (simplificando al suponer no concurrente e ignorando débil/suave/fantasma) hay una ejecución del GC que determina que no hay referencias activas al gráfico de objetos, incluido el cargador de clases. Los finalizadores se agregan a la cola del finalizador y luego se ejecutan. Luego, después de un paso posterior del GC, se puede recuperar la memoria. Esto requiere un GC completo que incluya el espacio genérico permanente, que generalmente no es frecuente y puede desactivarse.

De todos modos, no use singletons (con estado).

+0

¿Se recolectará un objeto de clase en este caso donde su cargador de clases no puede ser recolectado? Esto depende de la especificación del comportamiento del cargador de clases o puede depender de la implementación. –

+0

@EdStaub - Una clase NUNCA se recopila hasta que se pueda recoger su cargador de clases. Y un cargador de clases nunca se recopila hasta que se puedan recopilar TODAS las clases que cargó. –

+0

Y todavía se puede acceder a las referencias estáticas mientras se puede acceder a la clase. "Curiosamente," Tomcat anulará los campos estáticos. –

Cuestiones relacionadas