如何配置Spring以尽可能多地保存内存?

时间:2009-06-26 15:16:26

标签: java spring memory heap applicationcontext

我们在具有内存限制的半嵌入式设备上部署应用程序。我们正在分析应用程序的堆转储并攻击最大的消费者。

我们将Spring 2.5与Spring DM 1.1一起使用,我们注意到一些具有更复杂的Spring上下文的bundle正在耗尽相当多的内存,因为Spring似乎保留了包含所有被解析的BeanDefinitions的整个对象图。来自XML。我认为,一旦应用程序初始化并注入了所有内容,大部分内容都是不必要的。

Spring是否有配置选项可以控制此行为?在某种低内存模式下运行?扔掉所有不必要的东西?交易计算时间的大小?

5 个答案:

答案 0 :(得分:5)

我让团队成员对此有了更深入的了解并得到了一些有趣的结果。 Spring的默认配置非常不感兴趣,因为它的内存使用特别保守。有两个基本方面可以调整以获得显着收益:

  • 第一个是Spring OsgiBundleXmlApplicationContext内部的非公开属性,如果从该类扩展并覆盖customizeBeanFactory方法,则可以覆盖它。

我们这样做了:

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

将“setCacheBeanMetadata”属性设置为false会导致BeanDefinitions(基本上是基于XML的配置的编程镜像)在初始化后被丢弃。

  • 第二个更改 - 我们目前有一个原型 - 是Spring源代码的补丁,用于对集合进行延迟初始化。事实证明,许多代表Beans及其所有属性的内部Spring对象都有很多成员,默认情况下初始化为HashMaps和其他集合,但很少填充数据。更改Spring框架以便懒惰地初始化这些将节省另外大量的内存,但这是一个更具侵略性的更改。

答案 1 :(得分:1)

您可以使用BeanFactory保存某些内存 - 请参阅3.8.1. BeanFactory or ApplicationContext

  

由于ApplicationContext包含BeanFactory的所有功能,因此通常建议优先使用BeanFactory,除了一些有限的情况,例如在Applet中,内存消耗可能很关键,而且还有一些额外的千字节可能会有所作为。

答案 2 :(得分:0)

我不知道有什么办法让Spring在“轻”模式下运行。您可以尝试实现BeanFactoryPostProcessor并使用它从上下文中删除某些bean。我不知道这是否会导致内部Spring错误。

答案 3 :(得分:0)

如果你只在启动时使用Spring,所有bean都是有线的,那么你不需要应用程序上下文或关闭逻辑,你可以启动你的应用程序然后清除对应用程序上下文的所有引用。

答案 4 :(得分:0)

如果您的Spring配置使用AOP和加载时间编织,您可以使用aop.xml通过使用1.6.5中引入的AspectJ类型降级功能从AspectJ重新获得一些内存。

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

分析你的堆,如果找到很多RefType对象,上面的技巧会有所帮助。