2011-05-02 8 views
6

Tengo un código que estoy usando de otro equipo y he pasado varios días intentando rastrear una posible pérdida de memoria en mi aplicación. Obtengo un error OutOfMemory después de algunos redploys. He utilizado varias herramientas para rastrear la fuga, incluido YourKit Java Profiler y IBM Assisant Memory Analyzer de IBM. Mi aplicación es una aplicación Spring 3.0.5 J2EE que se ejecuta en WebSphere 6.1 utilizando controladores accionados por anotación spring-mvc.¿Podría declarar un ApplicationContext estático causar una pérdida de memoria? (Spring 3)

mayor parte de la investigación que he hecho puntos a una clase me parece muy sospechoso, lo llamaremos MyFactory y se ve así:

import org.springframework.context.ApplicationContextAware; 

public final class MyFactory implements ApplicationContextAware { 

    //this should be changed to be non static after getInstance is removed 
    private static ApplicationContext applicationContext; 

    public MyFactory() { 
     //empty 
    } 

    public static SettingObjectFactory getInstance() { 
     return (MyFactory) applicationContext.getBean("MyFactory"); 
    } 

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
     MyFactory.applicationContext = applicationContext; 
    } 


} 

Hay un montón de otra lógica en esta clase que dejé de lado que básicamente lee datos de una base de datos y los almacena en la memoria (cerca de la caché). Sin embargo, esta clase parece aferrarse a ApplicationContext después de que la aplicación se haya redistribuido.

¿El cargador de clases de esta clase está colgando en ApplicationContext o impidiendo que se limpie por completo? Sé que ya no necesitamos el método getInstance, y no veo la necesidad de hacer que esta clase tenga un ApplicationContext estático; me parece que Spring debería hacer cumplir el singleton-ness de esta clase.

Respuesta

6

Sí, mantener una referencia estática a un ApplicationContext puede provocar pérdidas de memoria en muchas configuraciones. La forma en que algunos servidores de aplicaciones y JVms interactúan con su carga de clases significa que los objetos a los que se hace referencia en los campos estáticos se pueden retener dentro del grupo de memoria de PermGen (al menos en la JVM de Sun Hotspot). Los appcontexts de Spring pueden ser gráficos de objetos muy grandes, dependiendo de cómo se ve la configuración de contexto.

La única solución permanente a esto que he encontrado es evitar el despliegue en caliente en entornos de producción, lo que evita por completo el problema del reciclaje de permgen. Sin embargo, sigue siendo molesto en un entorno de desarrollo.

+0

Gracias skaffman por confirmar mis sospechas. Lo REALMENTE extraño de este tema es que tenemos varias docenas de aplicaciones que usan este código, pero la aplicación en la que estoy trabajando parece ser la única que pierde memoria. La aplicación que gotea es la primera en usar Spring 3.0.5 (las aplicaciones anteriores estaban en 2.5.x). No puedo pensar en ninguna otra diferencia que haga que esta fuga aparezca ahora. ¿¿Algunas ideas?? –

+0

@Ryan: depende en gran medida de lo que contenga el contexto. BeanPostProcessors, por ejemplo, no se ven explícitamente anulados por el contexto cuando se apaga, y se basa en la recolección de elementos no utilizados para poner en marcha. No todos los contextos los usarán. – skaffman

Cuestiones relacionadas