How to configure Spring to save as much memory as possible?

We deploy the application on a semi-embedded device with limited memory. In an effort to save everything we can, we analyze heaps of application dumps and attack the largest consumers.

We use Spring 2.5 along with Spring DM 1.1, and we notice that some of our packages with more complex Spring contexts use quite a bit of memory, since Spring seems to support the entire graph object containing all the BeanDefinitions that were parsed from XML. I would suggest that most of this is not needed when the application was initialized and everything was entered.

Are there any configuration options for Spring that let me control this behavior? Run in some kind of low memory mode? Discard all unnecessary things? Trading time calculation for size?

+6
java spring heap memory applicationcontext
source share
5 answers

I had team members who looked deeper at this and had some interesting results. Spring in its default configuration is not very interested in the fact that it is especially conservative in memory usage. There are two main aspects that can be tuned for significant gains:

  • The first is an unpublished property inside Spring OsgiBundleXmlApplicationContext , which you can override if you go from this class and override the customizeBeanFactory method.

We did it like this:

 @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); } } 

Setting the setCacheBeanMetadata property to false causes BeanDefinitions (basically the software mirror of your XML-based configuration) to be dropped after initialization.

  • The second change that we have a prototype for is a patch for Spring source code to make lazy initialization of collections. It turns out that many of the internal Spring objects that Beans represent and all of their properties have many members, which are initialized by default with HashMaps and other collections, but very rarely populated with data. Changing the Spring structure to initialize these will lazily save another significant amount of memory, but this is a much more invasive change.
+5
source share

You can save some memory with BeanFactory - see 3.8.1. BeanFactory or ApplicationContext :

Since ApplicationContext includes all BeanFactory functionality, it is usually recommended to use it instead of BeanFactory, except in a few limited situations, for example, in an applet where memory consumption can be critical and a few extra kilobytes can make a difference.

+1
source share

I do not know how to make Spring work in easy mode. You can try to implement BeanFactoryPostProcessor and use it to remove certain beans from the context. I have no idea if this will lead to Spring's internal errors.

0
source share

If you use only Spring at startup, i.e. all beans are connected, and then you do not need the application context or shutdown logic, you can start your application and then clear all links to the application context.

0
source share

If your Spring configuration uses AOP time and load time, you can use aop.xml to recover some memory from AspectJ using the AspectJ downgrade function introduced in 1.6.5.

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

Analyze your bunch if you find many RefType objects, the trick described above will help.

0
source share

All Articles