`
yueguangyuan
  • 浏览: 337752 次
  • 性别: Icon_minigender_1
  • 来自: 新加坡
社区版块
存档分类
最新评论

Struts+Spring+Hibernate内存泄漏查找与处理

阅读更多

上个项目交付使用有两个月了,结果前几天客户告诉我他们的服务器崩溃了,先前服务器跑了一年都没有问题,结果装上我的东西跑了两个月就崩了,当时就说的我一身汗……心想人家两个月才崩溃的,我该怎么找这问题所在啊?

       把代码拿回来找原因,用JProbe监控服务器运行状态,结果搞了好久无法找到问题。后来朋友推荐我使用JProfiler监视线程,经过几天的痛苦折磨,总算是有一点发现,但目前还不能确定是否可以解决问题。

       具体情况:

       服务器一直是空载状态(客户基本不大用的,就是服务自己在跑,我觉得C/S架构更适合他们 :( ),服务器在跑的时候内存图就是一个锯齿型的样子:

      因为服务器中出了跑着Struts+Spring+Hibernate的Web服务之外还在后台开了一个运行Socket端口的线程,还有一个Quartz的线程,他们都会每隔一会就使内存用量升高一些,但是每过一段时间JVM自动运行GC就会使得内存又回复平稳状态。然后反复比较JProfiler提供的几个统计功能:Memory views、Heap walker、CPU views,

经过多次比较,再对各种配置参数修改(停止某些服务重新监视),发现CPU使用率基本没有什么变化,证明没有多余的线程在跑,在Heap walker和Memory views中发现最可能出现问题的就是用于开辟端口的StartThread线程和一个DiskStore线程,由于StartThread只是开辟一个端口,在没有外部使用这个端口的情况下它是不会增加什么东西的,所以就从DiskStore下手,Google一下,这是一个EHCache的一个类,应该是Hibernate用到了,因为我的程序里面用到了OpenSessionInViewFilter这个烂东东,实践证明这个东西很容易出错,速度慢,占用资源也多,真是不知道怎么还那么多人用,难道我配置的有问题?即便我配置的不得当(我的基本都是文档中的标配),那至少这个破烂反模式也是破坏了层的关系,与其说是个模式,不如说是Hibernate为自己的设计失误所做的一个不大情愿的补偿,所以以后再也不想用它,也不建议大家用,除非你非常熟悉这套东西,而且服务器的负载、流量低。

       扯远了,在发现这个DiskStore之后我就迷糊了,我根本就没有在Hibernate中配置二级缓存,为什么会有这个东西自己跑出来呢?这个问题我一直没有想清楚,也只能怪自己对这几个框架还是不够清楚,以后有机会要去补习一下,最好能抽时间研究一下源代码,说不定能有不小的收获(个人认为不是谁看源代码都会有大彻大悟的感觉,毕竟那可都是些大师们的手笔,我看过一点源代码,理解起来也很慢,尤其是关系复杂起来的时候就看不下去)。

      找了好半天,也没有和DiskStore太相关的东西,没办法就继续跑服务,结果两天两夜的双休跑下来,一个服务器直接重启,一个服务假死……郁闷了, 又去网上搜索了一下,居然有意外收获,发现了一个Spring的监听器IntrospectorCleanupListener,在一个博客上找到的,是对Spring文档的一段翻译,内容如下:

spring中的提供了一个名为org.springframework.web.util.IntrospectorCleanupListener的监听器。它主要负责处理由 
JavaBeans  Introspector的使用而引起的缓冲泄露。spring中对它的描述如下:
 
它是一个在web应用关闭的时候,清除JavaBeans Introspector的监听器.在web.xml中注册这个listener.可以保证在web 应用关闭的时候释放与掉这个web 应用相关的class loader 和由它管理的类
 
如果你使用了JavaBeans Introspector来分析应用中的类,Introspector 缓冲中会保留这些类的引用.结果在你的应用关闭的时候,这些类以及web 应用相关的class loader没有被垃圾回收.
 
不幸的是,清除Introspector的唯一方式是刷新整个缓冲.这是因为我们没法判断哪些是属于你的应用的引用.所以删除被缓冲的introspection会导致把这台电脑上的所有应用的introspection都删掉.
 
需要注意的是,spring 托管的bean不需要使用这个监听器.因为spring它自己的introspection所使用的缓冲在分析完一个类之后会被马上从javaBeans Introspector缓冲中清除掉.
 
应用程序中的类从来不直接使用JavaBeans Introspector.所以他们一般不会导致内部查看资源泄露.但是一些类库和框架往往会产生这个问题.例如:Struts 和Quartz.
 
单个的内部查看泄漏会导致整个的web应用的类加载器不能进行垃圾回收.在web应用关闭之后,你会看到此应用的所有静态类资源(例如单例).这个错误当然不是由这个类自身引起的.

      我觉得应用程序中的类从来不直接使用JavaBeans Introspector.所以他们一般不会导致内部查看资源泄露.但是一些类库和框架往往会产生这个问题.例如:Struts 和Quartz这一段可能就是我想寻找的答案,因为服务器仅仅是空载运行,我并没有在其中添加过多的服务器去消耗内存,那么原以为使用的几个框架是不会有内存泄漏这种问题的。而且当初也没怎么敢向这个方向考虑,但是Spring这份文档已经说明的比较清楚,刚好Struts和Quartz我都用到了,那么原因很有可能就处在这里。于是我就增加了这个IntrospectorLisener的监听器,期望有所收获。

 

=====================================================================================

开两个服务器,一个使用这个Lisener,另一个不使用,再同时运行24小时以后做比较,终于发现了喜人的成果:(一个是服务器,一个是我的办公用机,二者开销不大一样)

使用Lisener的服务器:

 

 

仍然是一个相对稳定的锯齿形状,而且Used heap size的峰值也没有超出启动时多少,让我们再看看没有使用Lisener是什么样子,这里我有个郁闷的问题,就是在长时间使用JProfiler之后,程序就会变得非常慢,CPU占用率直接100%,内存使用量也上升许多…… 可能是监控的程序泄漏太严重导致JProfiler也受影响

已经很明显了,没有用Lisener的服务器的内存用量明显呈上升趋势,然后再去查看Memory Views和Heap Walker,我这里会比较特殊,我想一般的程序级的内存泄漏早就可以暴露出来了,但是这里由于是框架上的问题,看了Memory Views和Heap我仍然没有很清晰的看到问题所在,因为数据显示占用量最大的是org.apache.catalina.startup.Bootstrap.main占用了最多的资源,这就涉及到更为底层的东西,我目前对Tomcat的运行机制还不是特别了解,但根据资料我猜测Tomcat加载的类最终都是交由Bootstrap来处理,相当于WebApp的根节点,那么占用最大资源也是在情理之中,而在Bootstrap之下加载上来的类也是Spring、Hibernate包下面的东西最多,那么这就符合最初的思路,在服务器运行过程中,Spring不停的运行的计划任务和OpenSessionInViewFilter,使得Tomcat反复加载对象而产生框架并用时可能产生的内存泄漏,则使用IntrospectorCleanupListener作为相应的解决办法。



 

分享到:
评论
3 楼 bitlong 2007-03-24  
我有一点不明白:
public class IntrospectorCleanupListener implements ServletContextListener {

public void contextInitialized(ServletContextEvent event) {
}

public void contextDestroyed(ServletContextEvent event) {
Introspector.flushCaches();
}

}

这个Lisnter实在WebappDestory的时候,contextDestroyed才有实现。
WebApp一直在运行,不会执行Introspector.flushCaches(); 阿

2 楼 yueguangyuan 2006-12-26  
Java查找内存泄露真是一件很令人头疼的事情,特别是泄露很不明显时候,这些工具虽然功能强大但是也并不那么易用,很难精确定位到某个制定的对象或类,而网上能找到的基本都是那种HelloWorld的例子,故意写个泄露来抓,能把这个总结出来我差不多搞了半个月的时间。
毕竟这种内存监视工具太贵了,国内公司很少有愿意花这个钱投资的,只能寄望于JMX能在后续的版本中更强一些
1 楼 andyyehoo 2006-12-26  
很好的文章,看来以后不管三七二十一,加上这个监听器就没错了,JProbe是个好东西,很好很好的东西,可惜用的人还不多。你也不算菜鸟了

相关推荐

    Struts2+Spring4+Hibernate4整合

    然而,整合过程需要注意性能优化,如合理使用缓存,避免内存泄漏,以及正确处理事务边界等。同时,随着Spring Boot的流行,现在更多项目倾向于采用Spring Boot进行快速开发,因为Spring Boot内置了许多默认配置,能...

    简单的S2SH登陆代码,其中包含数据库(struts2+spring+hibernate)

    Struts2、Spring和Hibernate是Java Web开发中的三大框架,它们各自负责不同的职责,共同构建了一个强大的MVC(Model-View-Controller)架构。在这个"简单的S2SH登陆代码"中,我们将探讨这三个框架如何协同工作,实现...

    SSH集成 Struts+spring+hibernate集成

    Hibernate与Spring的集成则通常通过Spring的HibernateTemplate或SessionFactory来完成,Spring可以帮助管理Hibernate Session,避免资源泄露。 在实际项目中,SSH集成的优势体现在以下几个方面: - **模块化**:每...

    学生选课管理系统(java开发,框架是spring+struts1.2+hibernate)

    该系统采用经典的Java开发技术,结合Spring、Struts1.2和Hibernate三大框架,构建了一个功能完备、稳定可靠的选课平台。 首先,Spring框架作为核心的依赖注入(DI)和面向切面编程(AOP)容器,负责管理应用中的...

    解决struts2.1.6+spring+hibernate 中文乱码

    该过滤器的主要作用是在请求结束后清理Struts2的ActionContext,防止内存泄漏等问题。 ### 总结 通过上述的配置,我们可以有效地解决基于Struts2.1.6、Spring及Hibernate框架的Web应用中出现的中文乱码问题。这些...

    spring+struts+hibernate框架

    SSH 为 Secure Shell 的缩写,由 IETF 的网络工作小组(Network Working Group)所制定;SSH 为建立在应用层和传输层基础上的安全协议。...利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。

    Struts+Spring+Hibernate整合开发框架搭建指南

    它还可以管理Struts的Action,使得Action实例可以在每次请求后被销毁,以防止内存泄漏。 2. **配置过程**: - 添加Spring支持:导入Spring的JAR包,配置web.xml文件以启用Spring的DispatcherServlet。 - 配置...

    struts2+spring+hibernate整合

    在IT领域,特别是Java开发中,Struts2、Spring与Hibernate的整合(通常简称SSH框架)是构建企业级应用的常见架构模式。这种整合能够充分利用每个框架的优势,提供MVC设计模式、依赖注入、以及对象关系映射等功能,...

    基于Struts+Spring+Hibernate+MySQL+Tomcat的中小企业办公自动化系统(源程序+开题报告+论文)

    基于Struts+Spring+Hibernate+MySQL+Tomcat的中小企业办公自动化系统(源程序+开题报告+论文) 系统的主要功能概述如下: (1) 用户身份验证模块 本系统功能的开发与设计,是完全针对公司内部进行办公管理...

    Struts+Hibernate+Spring的基本流程

    Struts+Hibernate+Spring(SSH)整合是Java Web开发中常见的技术栈,它结合了三个强大的框架,分别负责MVC架构、对象关系映射(ORM)以及依赖注入和AOP(面向切面编程)。SSH整合使得开发过程更加高效且易于维护。 ...

    strut+spring+hibernate注册登录系统

    Struts、Spring和Hibernate是Java开发中的三大主流框架,它们的整合使用在企业级应用开发中非常常见。这个"Strut+Spring+Hibernate注册登录系统"是一个基础的Web应用程序,旨在帮助初学者理解如何将这三个框架集成并...

    jsp源码项目申报系统(Struts2+Spring+Hibernate+Jsp+Mysql5)

    ### jsp源码项目申报系统(Struts2+Spring+Hibernate+Jsp+Mysql5) #### 一、项目概述 该项目是一款基于Java技术栈开发的项目申报系统,主要使用的技术框架包括Struts2、Spring、Hibernate以及前端技术JSP,并且...

    Struts2+spring+hibernate中的proxool连接池配置

    在Java Web开发中,Struts2、Spring和Hibernate是经典的MVC框架组合,它们共同构建了一个强大且灵活的后端架构。在这个组合中,数据库连接管理是一个关键环节,而Proxool作为一款轻量级的连接池库,常被用来优化...

    java+struts+hibernate+spring基础面试题

    Java是一种广泛使用的编程语言,以其跨平台、面向对象和自动内存管理等特性著称。Java的基础面试题通常涵盖...同时,熟悉Struts、Hibernate和Spring等框架的知识,将有助于在实际项目中解决复杂问题,提升开发效率。

    Struts2+Hibernate+Spring整合

    Struts2、Hibernate和...总的来说,Struts2、Hibernate和Spring的整合提供了完整的MVC架构,实现了业务逻辑与表现层的分离,提高了代码的可读性和可维护性。理解并掌握这三者的整合,对于Java Web开发者来说至关重要。

    struts2+hibernate+spring

    Struts2、Hibernate与Spring(通常简称为SSH)是Java Web开发中的三个流行框架。它们的结合可以极大地提高Web应用的开发效率和可维护性。具体来说: - **Struts2**:用于构建MVC架构的应用程序,它负责处理用户的...

    struts2+hibernate+Spring后台表格分页

    4. **后台表格分页实现**:在实际应用中,通常会有一个专门的Service层方法处理分页请求,该方法先通过Hibernate查询数据,然后使用Spring的ModelMap或者自定义的Dto将数据打包返回给Struts2 Action。Action再将结果...

    struts2+hibernate+spring登录注册系统

    Struts2、Hibernate和Spring(SSH)是Java开发中常用的一个集成框架,用于构建高效、可维护的企业级Web应用程序。这个“struts2+hibernate+spring登录注册系统”是一个利用SSH框架实现的用户身份验证和管理的示例...

    利用MyEclipse开发Struts+Hibernate应用

    Struts和Hibernate是两种在Java Web开发中广泛使用的开源框架,它们分别负责表现层和持久层的管理。MyEclipse是一款强大的集成开发环境,尤其适合Java EE项目的开发,包括Struts和Hibernate的集成。本教程将详细介绍...

    Struts + Hibernate网上书店实例

    Struts是一个基于MVC(Model-View-Controller)设计模式的框架,主要负责处理用户的请求和展示结果,而Hibernate则是一个对象关系映射(ORM)工具,用于简化数据库操作,将Java对象与数据库表进行映射。 在这个...

Global site tag (gtag.js) - Google Analytics