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

发布于 2024-07-25 17:51:24 字数 315 浏览 8 评论 0原文

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

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

心如狂蝶 2024-08-01 17:51:24

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

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.
來不及說愛妳 2024-08-01 17:51:24

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

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

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.

番薯 2024-08-01 17:51:24

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

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.

嘴硬脾气大 2024-08-01 17:51:24

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

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.

骄兵必败 2024-08-01 17:51:24

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文