Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > Java > Java EE性能问题解决办法-3
【标  题】:Java EE性能问题解决办法-3
【关键字】:Java,EE
【来  源】:http://blog.csdn.net/hdy007/archive/2007/01/15/1483321.aspx

Java EE性能问题解决办法-3

Your Ad Here

  IBM JVM内存管理模式

  IBM的JVM的机制有一点不同。它不是运行在一个巨大的继承HEAP中,它仅在一个单一的地区维护了所有的对象同时随着堆的增长来释放内存。 这个堆是这样运行的:在一开始运行的时候,它会很小,随着对象实例不断的填充,在需要执行垃圾收集的地方清除掉无效的对象同时把所有有效的对象紧凑的放置 到堆的底部。因此你可能猜测到了,如果想寻找可能发生的内存泄漏应该观察堆中所有的动作,堆的使用率是在提高?

  如何分析内存泄漏

  内存泄漏非常难确定,如果你能够确定是请求导致的,那你的工作就非常简单了。把你的程序放入到运行环境中,并在内存模拟器中运行,按下面的步骤来:

  •   1. 在内存模拟器中运行你的应用程序
  •   2. 执行使用方案(制造请求)以便让程序在内存中装载请求所需要的所有的对象,这可以为以后详细的分析排除不必要的干扰
  •   3. 在执行使用方案前对堆进行拍照以便捕获其中所有运行的对象。
  •   4. 再次运行使用方案。
  •   5. 再次拍照,来捕获使用方案运行之后堆中所有对象的状态。
  •   6. 比较这2个快照,找出执行使用方案后本不应该出现在堆中的对象。

  这个时候,你需要去和开发者交流,告诉他你所碰到的棘手的请求,他们可以判断究竟是对象泄漏还是为了某个目的特地让对象保留下来的。如果执行完 后并没有发现内存泄漏的情况,我一般会转到步骤4再进行多次类似的跟踪。比如,我可能会将我的请求反复运行17次,希望我的泄漏分析能够得到17个情况 (或更多)。这个方法不一定总有用,但如果是因为请求引起的对象泄漏的话,就会有很大的帮助。

  如果你无法明确的判断泄漏是因为请求引发的,你有2个选择:

  •   1. 模拟每一个被怀疑的请求直至发现内存泄漏
  •   2. 存配置一个内存性能跟踪工具

  第一个选项在小应用程序中是确实可用的或者你非常走运的解决了问题,但对大型应用程序不太有用。如果你有跟踪工具的话第二个选择是比较有用的。 这些工具利用字节流工具跟踪对象的创建和销毁的数量,他们可以报告特定类中的对象的数量状态,例如把Collections类作为特定的请求。例如,一个 跟踪工具可以跟踪/action/login.do请求,并在它完成后将其中的100个对象放入HASHMAP中。这个报告并不能告诉你造成泄漏的是代码 还是某个对象,而是告诉你在内存模拟器中应该留意那些类型的请求。把程序服务器放到产品环境中并不会使他们变敏感,而是跟踪性能的工具可以使你的工作变的 更简单化。

  虚假内存泄漏

  少数的一些问题看起来是内存泄漏实际上并非如此。

  我将这些情况称为假泄漏,表现在下面几种情况:

  •   1. 分析过早
  •   2. Session泄漏
  •   3. 异常的持久区域

  这章节对这些假泄漏都进行了调查,描述了如何去判断这些情况以及如何处理.

  不要过早分析

  为了在寻找内存泄漏的时候尽量减少出现判断错误的可能性,你应当在适当的时候分析堆。危险是:一些生命周期长的对象需要装载到堆中,因此在堆达到稳定状态且包含了核心对象之前具有很大的欺骗性。在分析堆之前,应该让应用程序达到稳定状态。

  为了判断是否过早的对堆进行分析,持续2个小时对跟踪到的分析快照进行分析,看堆的使用率是上升还是下降。如果是下降,保存这个时候的内存记录。如果是上升,这个时候就需要分析内存中的SESSION了。

  发生泄漏的session

  WEB请求经常导致内存泄漏,在一个WEB请求中,对象会被限制存储在有限的几个区域。这些区域就是:

  •   1. 页面区域
  •   2. 请求区域
  •   3. 上下文区域
  •   4. 应用程序区域
  •   5. 静态变量
  •   6. 长生命周期的变量,例如SERVLET

  当实现一些JSP(JAVASERVER页面)时,在页面上声明的变量在页面结束的时候就被释放,这些变量仅仅在这个单独的页面存在时存在。 WEB服务器会向应用程序服务器传送一系列参数和属性,也就是在SERVLET和JSP之间传输HttpServletRequest中的对象。你的动态 页面依靠HttpServletRequest在不同的组件之间传输信息,但当请求完成或者socket结束的时候,SERVLET控制器会释放所有在 HttpServletRequest 中的对象。这些对象仅在他们的请求的生命周期内存在。

  HTTP是无状态的,这意味着客户向服务器发送一个请求,服务器回应这个请求,这个传递就完成了,就是会话结束了。我们应该感激WEB页面帮我 们做的日志,这样我们就能向购物车放置东西,并去检查它,服务器能够定义一个跨越多请求的扩展对话。属性和参数被放在各自用户的HttpSession对 象中,并通过它让程序的SERVLET和JSP交流。利用这种办法,页面存储你的信息并把他们添加到HttpSession中,因此你可以用购物车购买东 西,并检查商品和使用信用卡付帐。作为一个无状态的协议,它总是客户端发起连接请求,服务器需要知道一个会话存在多长时间,到时候就应该释放这个用户的数 据。超过这个会话的最长时间就是会话超时,他们在程序服务器中设置。除非明确的要求释放对象或者这个会话失效,否则在会话超时之前会话中的对象会一直存 在。

  正如session是为每个用户管理对象一样,ServletContext为整个程序管理对象。ServletContext的有效范围是整 个程序,因此你可以利用Servlet中的ServletContext或者JSP应用程序对象在所有的Servlet和JSP之间让在这个程序中的所有 用户共享数据。ServletContext是最主要的存放程序配置信息和缓存程序数据的地方,例如JNDI的信息。

  如果数据不是存储这个四个地方(页面范围,请求范围,会话范围,程序范围)那就可能存储在下面的对象中:

  •   1. 静态变量
  •   2. 长生命周期的类变量

  每个类的静态变量被JVM(JAVA虚拟机)所控制,他们存在与否和类是否已经被初始化无关。一个类的所有实例共用一个存储静态变量的地方,因 此在任何一个实例中修改静态变量会影响这个类的其他实例。因此,如果一个程序在静态变量中存放了一个对象,如果这个变量生命周期没有到,那么这个对象就不 会被JVM释放。这些静态对象是造成内存泄漏的主要原因。

  最后,对象能够被放到内部数据类型或者长生命周期类中的成员变量中,例如SERVLET。当一个SERVLET被创建并且被装载到内存,它在内 存中仅有一个实例,采用多线程去访问这个SERVLET实例。如果在INIT()方法中装载配置信息,将他存储于类变量中,那么当需要维护的时候就可以随 时读出这些信息,这样所有的对象就用相同的配置。我常碰到的一个问题就是利用SERVLET类变量去存储象页面缓存这样的信息。在他们自己内部本身存贮这 些缓存配置是个不错的选择,但存贮在SERVLET中是最糟糕的情况。如果你需要使用缓存,你最好使用第三方控制插件,例如 TANGOSOL的COHERENCE。

  当在页面或者请求范围中利用变量存放对象的时候,在他们结束的时候这些对象会自动释放。同样,在SESSION中存放对象的时候,当程序明确说明此SESSION失效的或者会话执行超时的时候,这些对象才会自动被释放。

  很多看起来象内存泄漏的情况都是上面的那些会话中的泄漏。一个造成泄漏的会话并不是泄漏了内存而是类似于泄漏,它消耗了内存,但最终这些内存都 会被释放的。如果程序服务器发生内存溢出,判断是内存泄漏还是内存缺乏的最好的方法就是:停止所有向这个服务器所发的请求的对象,等待会话超时,看内存时 候会被释放出来。这虽然不会一定能够达到你要的目的,但是这是最好的分段处理方法,当你装载测试器的时候,你应该先挂断你内容巨大的会话而不是先去寻找内 存泄漏。

  通常来说,如果你执行了一个很大的会话,你应该尽量去减少它所占用的内存空间,如果可以的话最好能重构程序,以减少session所占据的内存空间。下面2种方法可以降低大会话和内存的冲突:

  •   1. 增大堆的空间以支持你的大会话
  •   2. 缩短会话的超时时间,让它能够快速的失效

  一个巨大的堆会导致垃圾回收花费更多的时间,因此这不是一个好解决方法,但总比发生OutofMemoryError强。增加足够的堆空间以使 它能够存储所有应该保存的有效值,也意味着你必须有足够的内存去存储所有访问你站点的用户的有效会话。如果商业规则允许的话最好能缩短会话超时的时间,以 减少堆占用空间的冲突。

  总结下,你应该依据合理性和重要性按下面的步骤依次去执行:

  •   1. 重构程序,尽量减少拥有session范围的变量所存储的信息量
  •   2. 鼓励你的客户在他们使用完后,明确的释放会话
  •   3. 缩短超时的时间,以便于让你内存尽快的得到回收
  •   4. 增加你堆空间的大小

  无论如何,不要让程序范围级的变量,静态变量,长生命周期的类存储对象,事实上,你需要在内存模拟器中去分析泄漏。


 
Java EE性能问题解决办法-4:【上一篇】
JDBC学习笔记-----jdbc性能优化:【下一篇】
【相关文章】
  • Java EE性能问题解决办法-4
  • Java EE性能问题解决办法-5
  • 话说Java(6):类与对象,上帝造人还是人造上帝
  • Java网络编程---I/O部分学习笔记整理
  • Java SE6调用Java编译器的两种新方法
  • TextSamplerDemo.java代码分析
  • 《JavaScript高级程序设计》学习总结之ECMAScript基础(一)
  • Sun让JSF光着身子来到Java Web世界
  • java 访问sql server(jdbc-odbc)
  • 谈新手修练J2EE武功及学SSH的方法
  • 【随机文章】
  • POI的一个bug问题
  • Lex和Yacc从入门到精通(6)-解析C/C++包含文件
  • Linux下增加Apache的rewrite Module
  • FW : 英文网址大全[分享]
  • MYSQL中怎样增加一个新用户
  • 在ASPX页面中输出XML
  • cisco3745 IOS丢失恢复过程(客户现场实际记录)
  • BSD程序开发版的立版宗旨
  • C语言入门之文件(2)
  • java中数值计算的精度问题
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 软讯网络 All Rigths Reserved.