Esto apunta a otro tipo de leak, en el que se crea una referencia entre una clase de sistema (de las cuales es propietario el Tomcat) y un objeto de mi aplicación, con lo cual la memoria utilizada por la versión vieja de la aplicación no puede ser reciclada y a la larga se produce un error del tipo:
java.lang.OutOfMemoryError: PermGen spaceLos pasos que utilicé para detectar el problema son:
- Crear un dump y levantarlo en jhat explica mi post anterior.
- Buscar en jhat las instancias de org.apache.catalina.loader.WebappClassLoader.
- Abrir las instancias una por una y quedarme solo con las que tienen la ruta de mi aplicación
- Las instancias que no están referenciadas por la clase org.apache.catalina.loader.WebappLoader son leaks.
- Elegir una de las instancias para estudiarla y copiar el Id del objeto.
- En el menú de jhat abrir Execute Object Query Language (OQL) query y ejecutar:
select heap.livepaths(o) from org.apache.catalina.loader.WebappClassLoader o where objectid(o) == "XXX"
Sustituyendo XXX por el id que se quiere estudiar (ej: 0xa3ed2510). - Copiar el resultado en un editor de texto
- Reemplazar ", " por ",\r\n" para obtener una línea por referencia
- Buscar referencias problemáticas:
- Java Local Reference
- System Class Reference
El problema en particular estaba en las clases del JDBC de Oracle: oracle.sql.AnyDataFactory y oracle.jdbc.driver.OracleDiagnosabilityMBean. Cómo no se que posible arreglo tendrá, decidí mover el driver al lib global de Tomcat y de esa forma puedo hacer redeploy de la aplicación sin que el driver deje la versión vieja colgada.
Nota:
Estoy usando Tomcat 6.0.24, en versiones anteriores de Tomcat no existía la detección de Leaks, a partir de esta versión se detectan automáticamente algunos leaks y dicha información queda en el log de Tomcat. En esta versión también se resuelve de forma automática el caso típico de leak debido a que no se desregistra el driver JDBC, pero otros leaks (como los que me enfrento ahora) no se resuelven automáticamente y Tomcat no es capaz de determinar con certeza cuales son las situaciones que efectivamente se convierten en un leak.