如何配置 Spring 以节省尽可能多的内存?

Posted

技术标签:

【中文标题】如何配置 Spring 以节省尽可能多的内存?【英文标题】:How can I configure Spring to save as much memory as possible? 【发布时间】:2009-06-26 15:16:25 【问题描述】:

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

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

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

【问题讨论】:

【参考方案1】:

我让团队成员对此进行了更深入的研究,并获得了一些有趣的结果。 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 框架以延迟初始化这些将节省大量内存,但这是一个更具侵入性的更改。

【讨论】:

【参考方案2】:

您可以使用 BeanFactory 节省一些内存 - 请参阅 3.8.1. BeanFactory or ApplicationContext:

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

【讨论】:

将我们所有的应用程序上下文定义重写为 Java 中的命令式 BeanFactory 调用根本不是一种选择。【参考方案3】:

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

【讨论】:

这就是我所害怕的,为了以防万一,我会再保留几天的问题。【参考方案4】:

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

【讨论】:

Spring 本身保留了对应用程序上下文的引用,我们没有明确地这样做。我不确定我们可以删除哪些引用。【参考方案5】:

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

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

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

【讨论】:

以上是关于如何配置 Spring 以节省尽可能多的内存?的主要内容,如果未能解决你的问题,请参考以下文章

如何从内存中删除多个熊猫(python)数据帧以节省 RAM?

我应该如何在 CodeIgniter4 中组织我的文件结构以节省内存?

使用 multiprocessing.map 时如何节省内存?

子类化 SimpleCursorAdapter 以包含 convertView 以节省内存

以节省内存的方式增长 data.frame

分析 Spring 应用程序以最小化启动时间