usage not leaks leak exist debug code avoid java garbage-collection classloader memory-leaks

not - memory leak java code



¿Cuándo y cómo se marca un cargador de clases java para la recolección de basura? (1)

Estamos creando varios cargadores de clases secundarios para cargar en varias subaplicaciones en un "contenedor" de aplicaciones Java, creando prototipos de despliegue en caliente. Cuando la ruta de clases de un cargador de clases en particular ha cambiado (es decir, se han agregado, eliminado, actualizado), el antiguo cargador de clases se desecha (sin referencia) y se crea un nuevo cargador de clases para la nueva ruta de clases de los archivos jar.

Después de actualizar el classpath, desencadenando la implementación en caliente, tomamos un volcado de pila. El volcado de almacenamiento dinámico (utilizando el Analizador de memoria) indica que los antiguos cargadores de clases no se estaban recolectando basura. Ciertas clases en el cargador de clases principal almacenaban en caché los cargadores de clases antiguos. Se invocaron las siguientes cosas para borrar estos cachés:

java.lang.ResourceBundle.clearCache(classLoader); org.apache.commons.logging.LogFactory.release(classLoader); java.beans.Introspector.flushCaches();

Incluso después de borrar los cachés anteriores, el cargador de clases anterior aún no se estaba recolectando basura. Las referencias restantes al cargador de clases incluyen lo siguiente:

  • las clases cargadas por el cargador de clases
  • java.lang.Package''s creado por el propio classloader
  • java.lang.ProtectionDomain creado por el propio cargador de clases

Todo lo anterior son referencias circulares dentro del cargador de clases, que deberían desencadenar una recolección de basura. No estoy seguro de por qué no lo es. ¿Alguien sabe por qué los antiguos cargadores de clases aún no están siendo recolectados con basura incluso con las referencias circulares?


Siempre escuché que la descarga del Classloader era problemática. En theoretically recolectan residuos cuando no hay referencias a las instancias de objetos y no es necesario descargar la clase, pero en la práctica parece ser más problemático. Las referencias sutiles pueden tener fugas y evitar que el Classloader sea ​​reclamado. En los servidores de aplicaciones, después de numerosos ciclos de redespliegue, a veces obtenía un OutOfMemoryError: PermGen space .

Todo esto para decir que creo que hay una referencia desagradable en algún lugar que impide que se recopile, tal vez el analizador de memoria no haya seguido el enlace correctamente. Parece que todo esto puede suceder, como se describe en estos artículos:

Además, no sé exactamente lo que estás haciendo, pero si puedes esperar a JDK 7, puedes echar un vistazo a AnonymousClassLoader . Se presentarán para admitir mejor el lenguaje dinámico, como se explica en esta publicación:

Espero que te ayude.