Boris Terzic
Boris Terzic

Reputation: 10948

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

We're deploying an application on a semi-embedded device that has memory constraints. Looking to save whatever we can we are analysing heap dumps of the app and attacking the biggest consumers.

We use Spring 2.5 together with Spring DM 1.1 and we notice that some of our bundles with more complex Spring contexts are using up quite a bit of memory since Spring seems to keep around the entire object graph containing all the BeanDefinitions that were parsed from the XML. I would assume that most of this is unnecessary once the app has been initialized and everything is injected.

Are there configuration options for Spring that allow one to control this behaviour? Run in some low memory mode? Throw away all unnecessary things? Trade computation time for size?

Upvotes: 7

Views: 4492

Answers (5)

Boris Terzic
Boris Terzic

Reputation: 10948

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.

Upvotes: 5

Gaël Marziou
Gaël Marziou

Reputation: 16294

If your Spring configuration uses AOP and load time weaving, you could use aop.xml to regain some memory from AspectJ by using AspectJ type demotion feature that was introduced in 1.6.5.

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

Analyse your heap, if you find many RefType objects, the trick above will help.

Upvotes: 0

Robert Munteanu
Robert Munteanu

Reputation: 68318

If you only use Spring at startup, i.e. all beans are wired and then you don't need the application context or the shutdown logic, you can start your app and then clear all references to the application context.

Upvotes: 0

cliff.meyers
cliff.meyers

Reputation: 17734

I'm not aware of any way to make Spring run in "light" mode. You could try implementing a BeanFactoryPostProcessor and use it to remove certain beans from the context. I have no idea whether that's going to lead to internal Spring errors however.

Upvotes: 0

Robert Munteanu
Robert Munteanu

Reputation: 68318

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

As the ApplicationContext includes all functionality of the BeanFactory, it is generally recommended that it be used in preference to the BeanFactory, except for a few limited situations such as in an Applet, where memory consumption might be critical and a few extra kilobytes might make a difference.

Upvotes: 1

Related Questions