Pérdidas de memoria en aplicaciones Java Platform, Enterprise Edition
Las pérdidas de memoria se presentan en varios tipos como, por ejemplo, pérdidas de hebra y ThreadLocal, pérdidas de ClassLoader, pérdidas de recursos del sistema y pérdidas de conexión. Los métodos para la detección de pérdida de memoria generalmente implican el examen de contadores JVMTI (Java™ Virtual Machine Tool Interface) o PMI (infraestructura de supervisión del rendimiento) para vigilar si hay un crecimiento lento en el uso del almacenamiento dinámico Java o nativo.
Pérdida de memoria del cargador de clases
Muchas pérdidas de memoria se manifiestan como pérdidas del cargador de clases. Una clase Java se identifica de forma exclusiva por su nombre y el cargador de clases que la ha cargado. Las clases con el mismo nombre se pueden cargar varias veces en una sola JVM, cada una en un cargador de clases diferente. Cada aplicación web obtiene su propio cargador de clases y esto es lo que WebSphere Application Server utiliza para aislar aplicaciones.
Un objeto retiene una referencia a la clase de la que es una instancia. Una clase retiene una referencia al cargador de clases que la cargó. El cargador de clases retiene una referencia a cada clase que carga. Retener una referencia a un solo objeto de una aplicación web fija cada clase cargada por la aplicación web. Estas referencias suelen permanecer después de volver a cargar una aplicación web. Con cada recarga, se fijan más clases, lo que conduce a un error de falta de memoria.
Las pérdidas de memoria del cargador de clases suelen estar causadas por el código de aplicación o el código desencadenado por JRE.
Pérdidas desencadenadas por JRE
Las pérdidas de memoria se producen cuando el código JRE (Java Runtime Environment) utiliza el cargador de clases de contexto para cargar un singleton de aplicación. Estos singletons pueden ser hebras u otros objetos que se han cargado mediante el JRE utilizando el cargador de clases de contexto.
- El cargador de clases de contexto se convierte en el cargador de clases de aplicaciones web.
- Se crea una referencia al cargador de clases de aplicación web. Esta referencia no es nunca recogida como basura.
- Fija el cargador de clases y todas las clases cargadas por él en la memoria.
Pérdidas desencadenadas por aplicación
- Clase ThreadLocal personalizada
- Instancia de clase de aplicación web como valor ThreadLocal
- Instancia de clase de aplicación web retenida indirectamente mediante un valor ThreadLocal
- Pseudopérdida de ThreadLocal
- ContextClassLoader y hebras creadas por aplicaciones web
- ContextClassLoader y hebras creadas por clases cargadas por el cargador de clases común
- Variables de clase estática
- Registro del controlador JDBC: destinos de RMI
WebSphere Application Server tiene ahora algunos medios de protección contra pérdidas de memoria al detener o volver a desplegar aplicaciones. WebSphere Application Server supervisa la actividad de aplicaciones y módulos y realiza acciones de diagnóstico cuando se detiene una aplicación o un módulo aislado.
- Detección: emitir avisos cuando se detecta una pérdida de memoria. Mediante una combinación
de llamadas API estándar y algunos trucos de reflexión cuando una
aplicación web se detiene, se cancela su despliegue o se vuelve a cargar.
WebSphere Application Server comprueba las
causas conocidas de pérdidas de memoria y emite avisos cuando se detecta una
pérdida de aplicación, de la manera siguiente:
[11/17/11 12:01:05:911 EST] 00000005 LeakDetection E CWMML0015E: The web application [WasSwat#WasSwatWeb.war] created a ThreadLocal with key of type [test.memleak.MyThreadLocal] (value [test.memleak.MyThreadLocal@216c691]) and a value of type [test.memleak.MyCounter] (value [test.memleak.MyCounter@21942ff]) but failed to remove it when the web application was stopped.
- La prevención está activada de forma predeterminada y sólo se aplica a pérdidas desencadenadas por JRE. JRE desencadenó pérdidas mediante la inicialización de singletons durante el arranque del servidor, cuando el cargador de clases del servidor de aplicaciones es el cargador de clases de contexto.
- Acción: tomar una acción proactiva para corregir las pérdidas de memoria. Estas acciones tienen valores predeterminados razonables y están configuradas caso por caso.
protected void com.ibm.ws.classloader.clearReferences(){ if(ENABLE_CLEAR_REFERENCES_JDBC) clearReferencesJdbc(); if(ENABLE_CLEAR_REFERENCES_THREADS) clearReferencesThreads(); if(ENABLE_CLEAR_REFERENCES_THREADLOCALS) clearReferencesThreadLocals(); if(ENABLE_CLEAR_REFERENCES_RMI_TARGETS) clearReferencesRmiTargets(); if(ENABLE_CLEAR_REFERENCES_STATICS) clearReferencesStaticFinal(); }
Causa de la pérdida | Cómo se arregla | Propiedades de la máquina virtual de Java de WebSphere para habilitar y controlar |
---|---|---|
Threadlocal | Renovar hebras en la agrupación de hebras durante un periodo configurable. La obtención de hebras de la agrupación permite que las hebras y threadlocals sean recogidas como basura. |
|
Hebras HttpClient de estado activo | Cambie la hebra al cargador de clases padre. |
|
Hebras de temporizador | Utilice el reflejo para detener cualquier nueva tarea que se pueda planificar. |
|
Hebras no controladas por JVM | Si la hebra se inicia utilizando un ejecutor, concluya el ejecutor o interrumpa la hebra. |
|
Controladores JDBC | Anule el registro de los controladores JDBC registrados por la aplicación web que la aplicación web olvidó. |
|
ResourceBundle | Borre la memoria caché de ResourceBundle de cualquier paquete que se haya cargado con este cargador de clases o cualquier cargador de clases del que este cargador sea padre. |
|
Destinos de RMI | Utilice el reflejo para borrar los valores de sun.rmi.transport.ObjectTable.implTable y sun.rmi.transport.ObjectTable.objTable. |
|
Variables de clase estática | WebSphere Application Server anula el valor de todas las variables de clase estática de clases que se han cargado mediante el cargador de clases de aplicación o módulo. |
|