声明静态 ApplicationContext 会导致内存泄漏吗? (春季3)
我从另一个团队获得了正在使用的代码,并且我花了几天时间试图追踪我的应用程序中可疑的内存泄漏。经过几次 redploy 后,我收到 OutOfMemory 错误。我使用了多种工具来追踪泄漏,包括 YourKit Java Profiler 和 IBM 的支持助手内存分析器。我的应用程序是一个 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 应该强制此类的单例性。
I've got code that I am using from another team and I have spent days trying to track down a suspected memory leak in my application. I get an OutOfMemory error after a few redploys. I have used several tools to track down the leak including YourKit Java Profiler and IBM's Support Assisant Memory Analyzer. My app is a Spring 3.0.5 J2EE app running on WebSphere 6.1 using spring-mvc annotation driven controllers.
Most of the research I have done points to a class I find very suspect, we'll call it MyFactory and it looks like this:
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;
}
}
There is a whole bunch of other logic in this class that I left out that basically reads data from a database and stores it in memory (near cache). However, this class seems to hang on to the ApplicationContext after the application has been redployed.
Is this class's classloader hanging onto the ApplicationContext or preventing it from being completely cleaned up? I know that we don't need the getInstance method anymore, and I don't see a need for making this class have a static ApplicationContext - it seems to me Spring should enforce the singleton-ness of this class.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,在许多设置中持有对 ApplicationContext 的静态引用可能会导致内存泄漏。某些应用程序服务器和 JVM 与其类加载交互的方式意味着静态字段中引用的对象可以保留在 PermGen 内存池中(至少在 Sun Hotspot JVM 中)。 Spring appcontexts 可以是非常大的对象图,具体取决于您的上下文配置。
我发现的唯一永久解决方案是避免在生产环境中进行热部署,这完全解决了永久回收问题。但在开发环境中它仍然很烦人。
Yes, holding a static reference to an ApplicationContext is liable to cause memory leaks in many setups. The way that some appservers and JVms interact with their classloading means that objects referenced in static fields can be retained within the PermGen memory pool (in the Sun Hotspot JVM, at least). Spring appcontexts can be very large object graphs, depending on what your context config looks like.
The only permanent solution to this that I've found is to avoid hot-deployment in production environments, which gets around the permgen recycling problem altogether. It's still annoying in a development environment, though.