I had team members have a deeper look at this and had some interesting results. Spring in its default configuration is very much not interested in being especially conservative in its memory usage. There are 2 basic aspects that can be tweaked for significant gains:
- The first is a non-exposed property inside the Spring
OsgiBundleXmlApplicationContext
that you can override if you extend from that 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 the BeanDefinitions
(basically the programmatic mirror of your XML based configuration) to be discarded after initialization.
- The second change - that we currently have a prototype for - is a patch for the Spring source code to do lazy initialization of collections. It turns out that many internal Spring objects that represent Beans and all their properties have a lot of members that are initialised to HashMaps and other collections by default but are very rarely filled with data. Changing the Spring framework to initialize these lazily will save another significant amount of memory but it is a much more invasive change.