Pregunta

Estamos implementando una aplicación en un dispositivo semi-integrado que tiene restricciones de memoria. Buscando ahorrar todo lo que podamos, estamos analizando los volcados de la aplicación y atacando a los mayores consumidores.

Usamos Spring 2.5 junto con Spring DM 1.1 y notamos que algunos de nuestros paquetes con contextos Spring más complejos están utilizando bastante memoria ya que Spring parece mantenerse alrededor del gráfico de objetos completo que contiene todas las BeanDefinitions que se analizaron del XML Supongo que la mayor parte de esto es innecesario una vez que la aplicación se ha inicializado y todo se inyecta.

¿Hay opciones de configuración para Spring que le permitan a uno controlar este comportamiento? Ejecutar en algún modo de poca memoria? ¿Tirar todas las cosas innecesarias? ¿Tiempo de cómputo comercial por tamaño?

¿Fue útil?

Solución

Los miembros del equipo tuvieron una mirada más profunda a esto y obtuve algunos resultados interesantes. Spring en su configuración predeterminada no está muy interesado en ser especialmente conservador en su uso de memoria. Hay 2 aspectos básicos que se pueden ajustar para obtener ganancias significativas:

  • La primera es una propiedad no expuesta dentro del Spring OsgiBundleXmlApplicationContext que puede anular si se extiende desde esa clase y anula el método customizeBeanFactory.

Lo hicimos así:

@Override
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    super.customizeBeanFactory(beanFactory);
    String cacheBeanMetadataSysProp = System.getProperty(CACHE_BEAN_METADATA, "true");
    if (cacheBeanMetadataSysProp != null
        && cacheBeanMetadataSysProp.equalsIgnoreCase("false")) {
        beanFactory.setCacheBeanMetadata(false);
    } else if (cacheBeanMetadataSysProp != null
        && cacheBeanMetadataSysProp.equalsIgnoreCase("true")) {
        beanFactory.setCacheBeanMetadata(true);
    }
}

Configuración de " setCacheBeanMetadata " false hace que la BeanDefinitions (básicamente el espejo programático de su configuración basada en XML) se descarte después de la inicialización.

  • El segundo cambio, para el que actualmente tenemos un prototipo, es un parche para el código fuente de Spring para hacer una inicialización diferida de las colecciones. Resulta que muchos objetos internos de Spring que representan Beans y todas sus propiedades tienen muchos miembros que se inicializan en HashMaps y otras colecciones de forma predeterminada, pero rara vez se llenan de datos. Cambiar el marco de Spring para inicializarlos perezosamente ahorrará otra cantidad significativa de memoria, pero es un cambio mucho más invasivo.

Otros consejos

Puede guardar algo de memoria con un BeanFactory; consulte 3.8.1. BeanFactory o ApplicationContext :

  

Como ApplicationContext incluye toda la funcionalidad de BeanFactory, generalmente se recomienda que se use con preferencia a BeanFactory, excepto en algunas situaciones limitadas, como en un Applet, donde el consumo de memoria puede ser crítico y algunos kilobytes adicionales. Podría hacer la diferencia.

No conozco ninguna forma de hacer que Spring se ejecute en " light " modo. Puede intentar implementar un BeanFactoryPostProcessor y usarlo para eliminar ciertos beans del contexto. Sin embargo, no tengo idea de si eso conducirá a errores internos de Spring.

Si solo usa Spring en el inicio, es decir, todos los beans están conectados y no necesita el contexto de la aplicación o la lógica de apagado, puede iniciar su aplicación y luego borre todas las referencias al contexto de la aplicación.

Si su configuración de Spring usa AOP y tejido de tiempo de carga, puede usar aop.xml para recuperar algo de memoria de AspectJ utilizando la función de degradación de tipo AspectJ que se introdujo en 1.6.5.

<weaver options="-Xset:typeDemotion=true"/>

Analiza tu montón, si encuentras muchos objetos RefType, el truco anterior te ayudará.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top