【问题标题】:Could declaring a static ApplicationContext cause a memory leak ? (Spring 3)声明静态 ApplicationContext 会导致内存泄漏吗? (春天 3)
【发布时间】:2026-02-19 17:50:01
【问题描述】:

我从另一个团队获得了我正在使用的代码,并且我花了几天时间试图在我的应用程序中追踪可疑的内存泄漏。几次重新部署后,我收到 OutOfMemory 错误。我使用了几种工具来追踪泄漏,包括 YourKit Java Profiler 和 IBM 的 Support Assisant Memory Analyzer。我的应用程序是一个 Spring 3.0.5 J2EE 应用程序,使用 spring-mvc 注释驱动的控制器在 WebSphere 6.1 上运行。

我所做的大部分研究都指向一个我觉得非常可疑的类,我们称之为 MyFactory,它看起来像这样:

import org.springframework.context.ApplicationContextAware;

public final class MyFactory implements ApplicationContextAware {

    //this should be changed to be non static after getInstance is removed
    private static ApplicationContext applicationContext;

    public MyFactory() {
        //empty
    }

    public static SettingObjectFactory getInstance() {
        return (MyFactory) applicationContext.getBean("MyFactory");
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        MyFactory.applicationContext = applicationContext;
    }


}

我忽略了这个类中的一大堆其他逻辑,它们基本上是从数据库中读取数据并将其存储在内存中(靠近缓存)。但是,在重新部署应用程序后,此类似乎会挂在 ApplicationContext 上。

这个类的类加载器是挂在 ApplicationContext 上还是阻止它被完全清理?我知道我们不再需要 getInstance 方法,而且我认为不需要让此类具有静态 ApplicationContext - 在我看来 Spring 应该强制此类的单例。

【问题讨论】:

    标签: java spring memory-leaks websphere


    【解决方案1】:

    是的,在许多设置中持有对 ApplicationContext 的静态引用可能会导致内存泄漏。一些应用服务器和 JVM 与其类加载交互的方式意味着静态字段中引用的对象可以保留在 PermGen 内存池中(至少在 Sun Hotspot JVM 中)。 Spring appcontexts 可以是非常大的对象图,具体取决于您的上下文配置。

    我发现的唯一永久解决方案是避免在生产环境中进行热部署,这完全解决了 permgen 回收问题。不过,在开发环境中它仍然很烦人。

    【讨论】:

    • 感谢 skaffman 证实了我的怀疑。这个问题真正奇怪的是我们有几十个应用程序使用这个代码,但我正在开发的应用程序似乎是唯一一个泄漏内存的应用程序。泄漏的应用程序是第一个使用 Spring 3.0.5 的应用程序(以前的应用程序是在 2.5.x 上)。我想不出任何其他差异会使这个泄漏现在出现。有什么想法吗??
    • @Ryan:这高度依赖于上下文包含的内容。例如,BeanPostProcessors 在关闭时不会被上下文显式地设置为空,而是依赖垃圾收集来启动。并非所有上下文都会使用这些。