En nuestra aplicación tenemos varios (actualmente muchos, unos 30) servicios web. Cada servicio web reside en su propio archivo WAR y tiene su propio contexto Spring que se inicializa cuando se inicia la aplicación.Aspectos que escanean demasiadas clases y la memoria caché de método llena la memoria
También tenemos varias clases de aspectos impulsadas por anotaciones que aplicamos a las clases de servicio web. En el principio la expresión poincut veía así:
@Pointcut("execution(public * my.package.service.business.*BusinessServiceImpl.*(..))")
public void methodsToBeLogged() {
}
Y AOP fue habilitada en servicios a través de la entrada en la configuración.
Pero cuando el número de servicios web creció, comenzamos a experimentar OutOfMemoryException
s en nuestros servidores. Después de hacer algunos perfiles y análisis, parece que la memoria está ocupada por la memoria caché que mantienen las instancias de la clase AspectJExpressionPointcut.
El caché de cada instancia era de aproximadamente 5 MB. Y como teníamos 3 aspectos y 30 servicios, resultó en 90 instancias con 450 MB de datos en total.
Después de examinar el contenido de la caché nos dimos cuenta de que contiene las instancias método de reflexión de Java para todas las clases existentes en el GUERRA incluso aquellos que no son parte del paquete de my.package.service.business. Después de modifing la expresión punto de corte para tener adicionalmente within
cláusula:
@Pointcut("execution(public * my.package.service.business.*BusinessServiceImpl.*(..)) &&
within(my.package.service.business..*)")
public void methodsToBeLogged() {
}
uso de la memoria se redujo a la normalidad. Y todas las instancias de AspectJExpressionPointcut tomaron menos de 1 MB todos juntos.
¿Alguien puede explicar por qué es eso? ¿Y por qué la expresión del primer punto no es suficiente? ¿Por qué el caché de AspectJExpressionPointcut
no se comparte?
¡Excelente respuesta! –