7

我们正在一个有内存限制的半嵌入式设备上部署一个应用程序。为了尽可能地保存我们正在分析应用程序的堆转储并攻击最大的消费者。

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

Spring 是否有允许控制这种行为的配置选项?在一些低内存模式下运行?扔掉所有不必要的东西?用计算时间换大小?

4

5 回答 5

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 源代码的补丁,用于对集合进行延迟初始化。事实证明,许多代表 Bean 的内部 Spring 对象及其所有属性都有很多成员,默认情况下初始化为 HashMap 和其他集合,但很少填充数据。更改 Spring 框架以延迟初始化这些将节省大量内存,但这是一个更具侵入性的更改。
于 2009-07-20T14:52:55.723 回答
1

您可以使用 BeanFactory 节省一些内存 - 请参阅3.8.1。BeanFactory 或 ApplicationContext

由于 ApplicationContext 包含 BeanFactory 的所有功能,因此通常建议优先使用它而不是 BeanFactory,除了一些有限的情况,例如在 Applet 中,内存消耗可能很关键,并且额外的几 KB 可能会导致不同之处。

于 2009-06-26T15:25:04.603 回答
0

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

于 2009-06-26T20:11:34.857 回答
0

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

于 2009-06-29T07:57:04.980 回答
0

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

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

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

于 2009-07-12T10:22:55.153 回答